嘿,我最近 2-3 天正在尝试调试这个程序。问题是,我正在构建一个客户端服务器体系结构,并且所有客户端在使用 Socket 连接的一定时间间隔后 ping 服务器(及其信息)。因此,在服务器端,当我尝试构建 ObjectOutputStream 时,程序会卡住。这是客户端的代码。
public void pingUpdate(){
Thread pingThread = new Thread() {
public void run() {
while(true) {
try {
ping_socket = new Socket( "localhost", 11111 );
ObjectOutputStream ping_objectOutputStream = new ObjectOutputStream( ping_socket.getOutputStream( ) );
ping_objectOutputStream.flush();
ping_objectOutputStream.writeObject( user );
ping_objectOutputStream.close();
ping_socket.close( );
}catch (Exception exception) {
exception.printStackTrace();
}
}
};
pingThread.start();
}
这是服务器的代码
public void run() {
while ( true ) {
try {
System.out.println("Server Listening" );
Socket client = null;
client = serverSock.accept();
System.out.println("Accepted" );
InputStream inputStream = client.getInputStream();
System.out.println("Input stream established" );
ObjectInputStream ois = new ObjectInputStream( inputStream );
System.out.println("Object streams established" );
User user = ( User ) ois.readObject( );
System.out.println("Object read" );
ois.close( );
client.close( );
}
catch (Exception e){
e.printStackTrace();
}
}
}
服务器程序打印直到“输入流已建立”并卡住。尽管我在客户端刷新了输出流,但我不知道为什么会发生这种情况。谢谢。
最佳答案
我无法重现挂起的客户端。我认为它必须如何将对象写入流而不随后刷新流,因为流仅在满时或关闭之前刷新。请使用finally block 关闭套接字和流。
我重写了您的源代码并发送字符串“Hallo,Server”而不是用户对象(您提供的代码中缺少该对象)。我在发送后添加了一点延迟,以免连接淹没服务器。
我已经在使用 JDK 1.8 Update 102 的 Win 8.1 上测试了代码,现在可以正常工作了。
客户:
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Client{
public static void main(String[] args){
new Client().pingUpdate();
}
public void pingUpdate(){
Thread pingThread = new Thread(){
@Override
public void run(){
while(true){
Socket ping_socket = null;
ObjectOutputStream ping_objectOutputStream = null;
try{
ping_socket = new Socket("localhost",
11111);
ping_objectOutputStream = new ObjectOutputStream(ping_socket.getOutputStream());
ping_objectOutputStream.writeObject("Hallo, Server");
ping_objectOutputStream.flush();
}
catch(Exception exception){
exception.printStackTrace();
}
finally{
try{
if (ping_objectOutputStream != null){
ping_objectOutputStream.close();
}
}
catch(IOException e){
e.printStackTrace();
}
try{
if (ping_socket != null){
ping_socket.close();
}
}
catch(IOException e){
e.printStackTrace();
}
}
// wait some time for the next ping
try{
Thread.sleep(1000);
}
catch(InterruptedException e){
e.printStackTrace();
}
}
}
};
pingThread.start();
}
}
服务器:
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server{
public void servePingUpdate(){
Thread pingThread = new Thread(){
@Override
public void run(){
ServerSocket serverSock = null;
try{
serverSock = new ServerSocket(11111);
while(true){
Socket client = null;
ObjectInputStream ois = null;
try{
System.out.println("Server Listening");
client = serverSock.accept();
System.out.println("Accepted");
InputStream inputStream = client.getInputStream();
System.out.println("Input stream established");
ois = new ObjectInputStream(inputStream);
System.out.println("Object streams established");
String message = (String) ois.readObject();
System.out.println("Object read: " + message);
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
if (ois != null){
ois.close();
}
}
catch(IOException e){
e.printStackTrace();
}
try{
if (client != null){
client.close();
}
}
catch(IOException e){
e.printStackTrace();
}
}
}
}
catch(IOException e1){
e1.printStackTrace();
}
finally{
try{
if (serverSock != null){
serverSock.close();
}
}
catch(IOException e){
e.printStackTrace();
}
}
}
};
pingThread.start();
}
public static void main(String[] args){
new Server().servePingUpdate();
}
}
编辑:TCP 协议(protocol)需要一些时间来进行 TCP 握手,服务器需要一些时间通过 System.out 输出行并关闭套接字。
如果没有等待,客户端会在 1-2 秒后抛出 java.net.BindException:地址已在使用中:连接,因为服务器没有可用端口。 对于低延迟 ping,UDP 协议(protocol)更好,请参阅 example code for a UDP pinger或者保持套接字打开并在每次 ping 时重复使用它。
关于java - 程序卡在 ObjectInputStream 构造函数处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40417331/