Java 使用ServerSockets和Sockets时,BufferedReader将挂起,并且连接似乎不';不能正确地形成
编辑:我已通过在服务器代码中添加一行更正了代码中的以下错误 我正在尝试编写一些套接字代码,允许我为一个游戏将数据从一台计算机发送到另一台计算机(为了简单起见,我们可以将其视为tic-tac-toe,不需要发送太多数据,只需发送几个数字)。为了实现这一点,我编写了两个类,Java 使用ServerSockets和Sockets时,BufferedReader将挂起,并且连接似乎不';不能正确地形成,java,sockets,bufferedreader,serversocket,Java,Sockets,Bufferedreader,Serversocket,编辑:我已通过在服务器代码中添加一行更正了代码中的以下错误 我正在尝试编写一些套接字代码,允许我为一个游戏将数据从一台计算机发送到另一台计算机(为了简单起见,我们可以将其视为tic-tac-toe,不需要发送太多数据,只需发送几个数字)。为了实现这一点,我编写了两个类,Server和Client。目前,我正在使用端口1234通过本地主机进行测试,并且我只使用了该程序的一个实例(尽管在尝试使用两个实例时也会出现同样的问题) 首先是代码,然后我可以更深入地了解这个问题,以及我做了哪些测试来试图找出问
Server
和Client
。目前,我正在使用端口1234通过本地主机进行测试,并且我只使用了该程序的一个实例(尽管在尝试使用两个实例时也会出现同样的问题)
首先是代码,然后我可以更深入地了解这个问题,以及我做了哪些测试来试图找出问题所在:
public class Server
{
private ServerSocket server;
private Socket socket;
private Client socketHandler;
private static final int DEFAULT_PORT = 1234;
public Server() { this(DEFAULT_PORT); }
public Server(int port)
{
Thread thread = new Thread()
{
public void run()
{
try
{
System.out.println("Attempting to Establish Connection");
server = new ServerSocket(port);
socket = server.accept();
socketHandler = new Client(port, socket); //THIS LINE ADDED
System.out.println("Server Online!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
//ADJUSTED
Client getSocketHandler()
{
return socketHandler;
}
public void kill()
{
try
{
if (socket != null) socket.close();
if (server != null) server.close();
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
socket = null;
server = null;
}
}
}
public class Client
{
public static final int DEFAULT_PORT = 1234;
public static final String DEFAULT_HOST = "localhost";
private static final String THUMP_THUMP = "thump thump";
private static final int PULSE = 1000;
private int port;
private String ip;
private Socket socket;
private BufferedReader input = null;
private PrintWriter output = null;
boolean closed = true;
String data = "";
public Client() { this(DEFAULT_PORT, DEFAULT_HOST, null); }
public Client(int port) { this(port, DEFAULT_HOST, null); }
public Client(int port, String ip) { this(port, ip, null); }
public Client(int port, Socket server) { this(port, DEFAULT_HOST, server); }
public Client(String ip) { this(DEFAULT_PORT, ip, null); }
public Client(String ip, Socket server) { this(DEFAULT_PORT, ip, server); }
public Client(Socket server) { this(DEFAULT_PORT, DEFAULT_HOST, server); }
public Client(int port, String ip, Socket server)
{
socket = server;
this.ip = ip;
this.port = port;
Thread thread = new Thread()
{
public void run()
{
try
{
initialise(server);
String line;
startHeartbeat();
while (isClosed()) {} //first it is closed, lets wait for it to open before we start waiting for it to close!
System.out.println("We are about to listen!");
while (!isClosed())
{
System.out.println("pre-read"); //this line was used to determine that the code was hanging on the next line
line = input.readLine(); //offending line
System.out.println("post-read"); //this line was used to determine when the block was lifted
if (line != null)// || line != THUMP_THUMP)
{
System.out.println(line);
data += line + "\n";
}
}
System.out.println(data);
kill();
System.out.println("Connection Closed!");
}
catch (SocketException e)
{
e.printStackTrace();
System.out.println("Server closed!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
private void initialise(Socket server)
{
try
{
if (server == null) socket = new Socket(ip, port);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
catch (IOException e) { e.printStackTrace(); }
}
public boolean post(String text)
{
synchronized(this)
{
output.println(text);
output.flush();
return !output.checkError();
}
}
public void kill()
{
try
{
if (input != null) input.close();
if (socket != null) socket.close();
}
catch(IOException e) { e.printStackTrace(); }
finally
{
input = null;
socket = null;
}
}
public void killOutputStream()
{
try
{
if (output != null) output.close();
}
catch (Exception e) { e.printStackTrace(); }
finally
{
output = null;
}
}
//////////////////////////////////
///////// Socket Control /////////
//////////////////////////////////
synchronized boolean isClosed()
{
return closed;
}
synchronized void setClosed(boolean b)
{
closed = b;
}
//We need to make sure that the socket is still online, to ensure the reading stops when the connection closes.
void startHeartbeat()
{
Thread heartbeat = new Thread()
{
public void run()
{
while (output != null)
{
setClosed(post(THUMP_THUMP) ? false : true); //post returns true on success
synchronized(this)
{
try
{
this.wait(PULSE);
}
catch (InterruptedException e) {}
}
}
setClosed(true);
}
};
heartbeat.setDaemon(true);
heartbeat.start();
}
}
问题
当客户端启动时(在创建服务器之后),它无法读取通过(甚至心跳)发送的任何数据,事实上,代码不会经过读取线程中的line=input.readLine()
(从现在起称为违规行),除非服务器断开连接(见下文)
以下是定期测试的顺序:
调用Server()
,得到的Server
存储在serverConnection
变量中
Client(serverConnection!=null?serverConnection.getSocket():null)
被调用,新的Client
存储在clientConnection
中
因为我们可以使用heartbeat测试它是否工作,所以不需要发送其他数据,通过调用serverConnection.kill()
,然后在等待一段时间后调用clientConnection.killOutputStream()
来终止服务器
这就是结果:
Attempting to Establish Connection Server Online!
We are about to listen!
Connection Closed!
其中,空行表示在连接过程中接收到的非空数据,即不存在任何数据
我期望:
Attempting to Establish Connection
Server Online!
We are about to listen!
thump thump
thump thump
thump thump (and so on, every second)
Connection closed!
我花时间执行不同的测试,用相同的测试格式注释掉或稍微更改代码(特例除外,第6号),并进行了以下观察:
观察结果
readline()
方法开始处理时(心跳停止前不久),它在流中检测不到任何内容,甚至THUMP\u-THUMP
readline()
方法开始处理,结果检测不到任何内容,heartbeat将其切断。无SocketException
,即使它是预期的SocketException
,提示套接字已关闭netstat-an
,当服务器启动时,端口1234正在侦听。当客户端连接时,它仍在侦听,这意味着没有连接Client(null)
这是非主机的客户端代码。信息技术
导致端口读取建立,并且python服务器
回响“砰砰”的一声,java代码就成功了
读它。没有绞刑,它工作得很好作为一个补充说明,测试代码是通过一个用javafx(不是fxml)编写的简单的极简GUI运行的,无论这是否是一个问题,我肯定,我认为不会,因为它与Python服务器一起工作。这段代码是用Java 8编译的。我有点不明白为什么您认为它会比input.readLine更进一步()考虑到服务器端没有处理输入/输出 客户端/服务器连接就像一场网球比赛,因为一方发球另一方必须先接到球,然后再发回(可能有不同的信息)。服务器端必须处理从start heartbeat方法收到的输入,然后向您发回响应。input.readLine()函数将阻塞线程,直到它从另一端接收数据为止,因此是的,代码将在那里停止,并等待服务器将“网球”发回。在服务器类中,您应该添加一个处理心跳输入的输入和输出流,并将一串数据发回客户端 服务器:
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
String response = "thump thump";
while(true){
is.read();
os.write(response.getBytes());
os.flush();
}
在本例中,客户端应保持不变,只需将上述代码添加到服务器。很抱歉,您的代码看起来很混乱,首先,您没有将任何数据从服务器发送到客户端,服务器也没有发送到客户端