我正在尝试在Java创建一个多客户机/服务器应用程序。我有些问题因为我的线好像纠缠在一起了...这就是我要做的。
>
我有一个服务器类,它通过使用以下代码来接受客户端:
while(true){Socket Socket=ServerSocket.Accept();}
我的服务器应该记住所连接的客户端,因此我使用该套接字创建一个名为ClientThread的新线程,并将该线程放在服务器上的列表中
该线程侦听从客户端发送的命令对象。如果它接收到一个命令,它需要将其发送到服务器实例以进行进一步的处理(而不需要在那个ClientThread上创建一个新的服务器实例)。我尝试在创建线程时将服务器实例添加到线程中。(这条路对吗?)
我的服务器还应该能够在任何时候将对象发送回客户端(1个或多个)。我尝试使用保存在ClientThread中的socket.getOutputStream()
来实现这一点
我应该如何组织我的线程,这样每个客户端都在不断地监听从服务器接受对象,并且他们可以随时向服务器发送对象。
我知道这并不是一个具体的问题,但如果您知道一些可能对这个用例有帮助的信息或教程,我将非常感谢。
顺便说一句:我知道如何创建套接字和发送(可序列化的)对象等等。我只想着如何组织一切
由于您已经了解了套接字和线程,所以我给您发送了idea pseudo代码(如果需要特定部分的代码就让我知道)
您没有提到的一件事是如何跟踪客户机,通过它的IP或任何其他方法,如ID?任何给定的设备是否可以使用不同的客户端ID打开多个连接?或者您只接受每个设备的一个连接?在任何情况下,如果一个客户已经在列表中,你应该怎么做?您会将创建的线程与新的套接字进行通信吗?你会毁掉那根线然后再创造一根新线吗?或者你会忽略这个新请求?
这是我的想法(取自一个正在工作的应用程序):
服务器准备服务器套接字并在接受状态下等待。
客户机连接后,服务器启动一个线程来处理客户机,并通过accept命令传递它刚刚创建的套接字。当参与客户机的线程启动时,它从客户机接收的第一条消息应该是一个密码或特殊签名,以便让客户机进入(这是可选的)。
服务器代码:
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
}
你似乎有纠缠的线和物体。我会的
a)确保您没有在任何地方扩展线程或调用对象xxxxThread。使用ExecutorService来管理线程是一个好主意。
b)有一个简单的模型来响应客户端命令,例如每个客户端线程读取一个任务,然后执行一个任务。
c)对每个连接都有一个包装器,例如使用sendMessage方法。
我在Java开发了一个客户端-服务器游戏(称为“Set”)。 在调试过程中遇到了一个非常尴尬的问题: 如果在同一台机器上同时运行客户端和服务器(客户端连接到localhost),这个游戏工作得很棒(如果我运行服务器和大量客户端的话也是如此)。 但是,如果我在两台不同的机器上运行客户端和服务器,那么客户端和服务器都挂起了Inputstream readLine方法。 我会提到我正在使用writeBy
在Mac OS X 10.8机器上,我有一台Tomcat 7.0.40服务器和一台客户端,都在本地运行。通过三方握手建立TCP连接,然后立即从服务器发送FIN、ACK和RST。客户端收到“来自服务器的文件结束”或“连接重置”。 TCP序列: 客户端SYN 服务器SYN,确认 客户端确认 服务器[TCP窗口更新]确认字符 服务器FIN,确认字符 客户端确认字符 服务器[TCP Dup确认字符]确认字
有没有一种简单的方法可以使用java程序重现tcp CLOSE_WAIT状态? 我有一个遗留的java应用程序存在这个问题,我希望能够重现它,以便测试我的修复。 谢谢
[服务器]:
编辑2:我切换到,并用包装客户端工厂,这样设备就可以很好地到达后端。但是当后端发回一些东西时,我会得到错误的出站套接字,客户机套接字死亡。我认为这是因为后端没有正确路由消息所必需的头。如何捕获此信息?我的配置类如下:
真的需要你帮忙。 我的项目是通过电缆连接两台PC机,并使用tcp套接字将客户端文本框形式的字符串发送到服务器。问题是ATI只能发送一个字符串,然后连接就会关闭。 注意:某个端口上的连接将在表单加载中建立并成功。