我正在创建一个聊天服务器,我不能得到一个以上的连接建立,我相信这是由于只有一个套接字。我读到一个线程能够处理多个套接字连接在同一时间,但每个客户端必须有自己的套接字。就像墙上的插座。每个插头必须有一个插座。我如何为每个客户端创建一个套接字来与服务器通信?我将提供一些代码来帮助大家基于这些代码。这里是接受单个套接字(连接)的地方。
private void waitForConnection() throws IOException
{
connection = server.accept();
showMessage("nNow connected to " + connection.getInetAddress().toString());
clientCount += 1;
}
下面是在服务器启动时调用的代码:
public void startRunning()
{
try
{
server = new ServerSocket(1337, 10);
while(true)
{
try
{
showMessage("Waiting For a Player To Connect...");
waitForConnection();
setupStreams();
whileChatting();
}
catch(EOFException eofException)
{
showMessage("n Server ended the connection! ");
}
finally
{
closeConnections();
}
}
}
catch(IOException ioException)
{
ioException.printStackTrace();
}
}
现在,这段代码对于第一个连接的客户端可以完美地工作。其他的都无法连接。
你应该让一个线程总是执行socket.accept()
。即:
- 当您接收到客户端(通过
socket.accept()
)时,您应该- 启动一个新的
Thread
,这将从现在开始照顾客户端。(我将其命名为Thread
扩展类ClientNanny
); - 然后返回运行
socket.accept()
。
- 启动一个新的
你的waitForConnection()
方法应该是这样的:
private List<ClientNanny> clients = new ArrayList<ClientNanny>();
private void waitForConnection() throws IOException
{
while (true) { /* or some other condition you wish */
connection = server.accept(); /* will wait here */
/* this code is executed when a client connects... */
showMessage("nNow connected to "
+ connection.getInetAddress().toString());
ClientNanny nanny = new ClientNanny(connection); /* call a nanny to take
care of it */
clients.add(nanny); /* make sure you keep a ref to it, just in case */
nanny.start(); /* tell nanny to get to work as an independent thread */
clientCount += 1; /* you dont need this: use clients.size() now */
}
}
如果你没有注意到,ClientNanny
应该是这样的:
class ClientNanny extends Thread {
ClientNanny(Socket baby) {
this.myBaby = baby;
}
@Override
public void run() {
bed.put(myBaby); /* and probably other commands :) */
}
}
现在,您应该注意到下面突出显示的代码…
try
{
showMessage("Waiting For a Player To Connect...");
waitForConnection();
setupStreams(); /* <--------- THIS LINE! HI! I'M A HIGHLIGHT! */
whileChatting(); /* <--------- THIS LINE! HI! I'M A HIGHLIGHT TOO! */
}
当您按照我的建议更改waitForConnection()
时,将不会执行(因为waitForConnection()
将继续在while(true)
循环内滚动)。也许你可以把socket.accept()
放在它自己的线程上…不管怎样,我相信你能从现在开始承担,好吗?
<一口> p。:作为最后一个指针,上面的解决方案使用new Thread()
(或new ClientNanny()
),因为它是解释问题的最简单方法。然而,最优的解决方案可能涉及到使用ExecutorService
(粗略地说,是一个线程池),正如在这个答案中迅速指出的那样。一口>
你的整个代码结构是错误的:
waitForConnection();
setupStreams();
whileChatting();
这不能做你需要的。您的循环应该只接受连接,然后为每个处理该套接字上的所有I/O的线程启动一个新线程。请参阅Java教程的自定义网络部分。
你的套接字代码应该像这样:
create server socket
while true (or quit received) {
accept connection
spawn thread to handle communication
}
也就是说,需要为每个连接生成一个线程。然后每个线程都可以执行whileChatting(),而不是占用主线程。
的例子:
while (true) {
try {
// listen for client connections
Socket s = svr.accept();
// start a separate thread to handle this client's communications
new ChatClientHandler(s).start();
}
catch (IOException e) {
// print out the error, but continue!
System.err.println(e);
}
}