我编写了一个Java套接字服务器,它将保持连接活动,直到客户端断开连接。我的客户端代码将继续将消息推送到此服务器应用程序。
但是当我运行这些程序一段时间时,我似乎也是一个不寻常的条件,在不可预测的时间内从客户端读取输入流时,服务器将挂起。它始终挂在inData.read(b)
,因为我看到它打印了#34;接收......"发生此问题时的日志&#34 ;;即使我杀了我的客户端,服务器应用程序仍然挂在那里。
但是当我在发生此问题后运行服务器应用程序的控制台上按Ctrl+C
时,它将继续工作。这真令人讨厌。
无论如何都能很好地解决这个不寻常的问题吗?
服务器代码:
static ServerSocket server;
try {
server = new ServerSocket("1234");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Socket socket = null;
String inIp = null;
BufferedInputStream inData;
BufferedOutputStream outData;
while (true) {
try {
synchronized (server) {
socket = server.accept();
}
inIp = String.valueOf(socket.getInetAddress());
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("Incoming connection " + inIp);
}
while (true) {
inData = new BufferedInputStream(socket.getInputStream());
outData = new BufferedOutputStream(socket.getOutputStream());
String reply = "Hey";
byte[] b = new byte[10240];
String data = "";
int length;
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("InetAddr = " + inIp + ", receiving...");
}
// read input stream
length = inData.read(b);
data += new String(b, 0, length);
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("Data Length: " + length + ", Received data: " + data);
}
// output result
outData.write(reply.getBytes());
outData.flush();
}
} catch (Exception e) {
String tempStr = e.toString();
Log4j.log.error("Service error during executing: " + tempStr);
}
}
客户代码:
Socket client = new Socket();
InetSocketAddress isa = new InetSocketAddress("127.0.0.1", "1234");
String data = "Hi";
while(true) {
try {
if(!client.isConnected())
client.connect(isa, 30000);
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
// send msg
out.write(data.getBytes());
out.flush();
System.out.println("Message sent, receiving return message...");
// get return msg
int length;
byte[] b = new byte[10240];
// read input stream
length = in.read(b);
retMsg = new String(b, 0, length);
System.out.println("Return Msg: " + retMsg);
Thread.sleep(60000);
} catch (java.io.IOException | InterruptedException e) {
System.out.println("Socket Error!");
System.out.println("IOException :" + e.toString());
}
}
答案 0 :(得分:2)
try {
server = new ServerSocket("1234");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
不要写这样的代码。 catch
块应该在最后,并且取决于new ServerSocket
成功的所有代码都应该在try
块内。
synchronized (server) {
socket = server.accept();
}
此处不需要同步。
while (true) {
inData = new BufferedInputStream(socket.getInputStream());
outData = new BufferedOutputStream(socket.getOutputStream());
问题的很大一部分,如果不是全部的话,就在这里。每次围绕此循环,您都会继续创建新的缓冲流,这意味着以前的流缓冲的任何内容都会被丢弃。所以你输了输入。您应该在循环之前创建这两个流。
while(true) {
try {
if(!client.isConnected())
client.connect(isa, 30000);
这毫无意义。去掉。您尚未显示client
套接字是如何创建的,但如果您创建了它未连接,则应在进入此循环之前将其连接起来。
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
这里你必须再次在循环之前创建这些流。