在Java中设置多客户端/服务器TCP连接

问题描述:

我正尝试在Java中创建多客户端/服务器应用程序。我有很多问题,因为我的线程似乎纠结...这是我想要做的。在Java中设置多客户端/服务器TCP连接

  1. 我有一个服务器级,通过使用此片的代码接受客户端:

    而(真){ Socket套接字=的ServerSocket.accept(); }

  2. 我的服务器应该记住连接,所以我创建了一个名为ClientThread与插座新的线程,并将该线程在一个列表服务器上的客户端

  3. 线程监听命令对象从客户端发送。如果它收到一个命令,它需要将它发送到服务器实例进行进一步处理(无需在该ClientThread上创建一个新的服务器实例)。我试图通过在创建时向此线程添加服务器实例来完成此操作。 (这是正确的方法吗?)

  4. 我的服务器还应该能够随时将对象发送回客户端(1个或更多)。我试图通过使用socket.getOutputStream()被保存在ClientThread

我应如何组织我的主题让每一个客户端不断听取接受来自服务器对象要做到这一点,他们可以发送对象到服务器在任何时候。

我知道这不是一个真正具体的问题,但如果你知道一些信息或教程可能会有所帮助这个用例,我会非常感激。

顺便说一句:我知道了如何创建套接字和发送(序列化)对象等..我只是停留在如何组织的一切

+1

考虑使用了Netty(http://netty.io/)这类任务 – hoaz 2013-05-13 17:15:30

您似乎已经缠线和对象。我会

a)确保你没有扩展任何线程或调用你的对象XxxxThread。使用ExecutorService来管理你的线程是一个好主意。

b)具有用于响应客户端命令的简单模型,例如,每个客户端线程读取一个任务,然后执行任务。

c)为每个连接都有一个包装,例如:使用sendMessage方法。

既然你已经知道了插座和线程,我送你的想法伪代码(案需要特定的代码部分只是让我知道)你没有提到

的一件事是如何跟踪客户,通过其IPo通过任何其他方法如ID?任何给定设备是否可以使用不同的客户端ID打开多个连接?或者你只能接受每个设备一个连接?无论如何,如果一个客户已经在列表中,你应该做什么?你会将创建的线程传递给新的套接字吗?你会摧毁该线程并创建一个新线程?或者,也许你会忽略这个新的要求?

这是我的想法(从工作应用程序中获得):

服务器准备服务器套接字,并等待在接受状态。

一旦客户端连接,服务器启动一个线程,以通过使用accept命令传递刚创建的套接字的客户端。当出席客户端的线程启动时,它从客户端收到的第一条消息应该是密码或特殊签名以让客户端进入(这是可选的)。

Server代码:

Prepares the server socket which listen in a well known port 
Clear client list; 

While (!Terminated) 
{ 
     // if you want to impose a limit for connections, check it here: 
     if (Is the list of connected client full?) 
     { 
      Sleep(reasonable time in seconds or miliseconds); 
      continue; 
     } 
     ClientSocket = ServerSocket.Accept(); 
     if the client's IP is already in the list 
     { 
      depends on what you want to do. 
     } 
     else 
     { 
      Add client's IP to the list 
      Start (create) new client Tread(ClientSocket); 
     } 
} 
// when server finish 
If (client list is not empty?) 
{ 
    Kill all threads 
    or 
    Wait until all threads are done 
    or 
    Wait an amount of time and then kill those remaining. 
} 

线程的客户端代码:

// This is optional, just to make sure a valid client is connected 
Read packet from ClientSocket 
if (!Is_the_passport_packet) 
{ 
    close socket; 
    return; 
} 

// if passport is not required, start here 
Try 
{ 
    While (!Terminated) 
    { 
     if (read packet from client); 
     { 
     switch (packet.Command) 
     { 
// In your question you said you want the Server thread to process the request 
// I guess you have your requirements to do so, 
// anyway, you must use a mutex o some other synchronization method. 
      case TASK_1: 
       [sync] process TASK_1(packet, ClientSocket); 
       break; 
      case TASK_2: 
       [sync] process TASK_2(packet, ClientSocket); 
       break; 
      etc …. 

      case WORK_DONE: 
       Close Socket; 
       return; 

      default: 
       Log(received an unknown command: packet.command); 
       break; 

     } 
     } 
     else if (Client has quit (closed/broken socket)) 
     { 
     // as you may know, a socket is consider shutdown when you received a 0 length data 
     // and a broken connection when received -1 in either case all you have to do is 
     Close Socket; 
     return; 
     } 
    } 
} 
catch (Exception e) 
{ 
    Log(received an exception: e.message); 
} 
finally 
{ 
    Remove this client from the client's list 
}