客户端程序
public class SocketClient {
public static void main(String[] args) throws Exception {
while(true){
Thread.sleep(5000);
new ClientThread().start();
}
}
}
class ClientThread extends Thread {
public void run() {
Socket socket = null;
InputStream in = null;
OutputStream out = null;
try {
socket = new Socket("10.1.24.147", 8888);
in = socket.getInputStream();
out = socket.getOutputStream();
System.out.println("Established a connection...");
String text = "B7A30350BE4F9F58482576B600239D54?Open";
byte[] block = new byte[500];
System.out.println("begin to write");
out.write(text.getBytes());
out.flush();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
System.out.println("begin to read");
int num = in.read(block); //A
while (num > 0) {
System.out.println("in while");
bOut.write(block, 0, num);
num = in.read(block);
}
System.out.println("read finished");
System.out.println(bOut.toString());
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
//out.close(); //B
} catch (Exception e) {
}
try {
//in.close(); //B
} catch (Exception e) {
}
try {
//socket.close(); //B
} catch (Exception e) {
}
}
}
}
服务端程序
public class SocketServer {
public SocketServer() {
try {
ServerSocket server = null;
try {
server = new ServerSocket(8888);
System.out.println("Server starts...port = "+server.getLocalPort());
} catch (Exception e) {
System.out.println("Can not listen to. " + e);
}
while (true) {
new ServerThread(server.accept()).start();
System.out.println("server.accept() starts...");
}
} catch (Exception e) {
System.out.println("Error. " + e);
}
}
public static void main(String[] args) {
new SocketServer();
}
}
class ServerThread extends Thread {
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
InputStream in = null;
OutputStream out = null;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
byte[] block = new byte[500];
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
System.out.println("begin to read");
int num = in.read(block);
while (num > 0) {
System.out.println("in while");
bOut.write(block, 0, num);
System.out.println("in while,begin to read");
num = in.read(block); //H
}
System.out.println("read finished");
System.out.println(bOut.toString());
System.out.println("begin to write");
out.write(bOut.toString().getBytes());
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//out.close(); //I
} catch (Exception e) {
}
try {
//in.close(); //I
} catch (Exception e) {
}
try {
//socket.close(); //I
} catch (Exception e) {
}
}
}
}
观察到的现象
服务端读取不到客户端发送的数据;客户端也读取不到服务端应答的数据。
客户端堵在A处,服务端堵在H处。
服务端阻塞在H处,服务端已经read了一次,并取到数据,准备read第二次的时候,由于流中已经没有数据,而read总是尝试读取更多的数据,所以堵在H处。
客户端堵在A处,是因为服务端没有写数据,因此流中没有数据可读。
也就是说,当socket流中没有数据的时候,read会阻塞,并等待超时,如果没有设置超时,就永远等待(这和读取文件不同)。
Client-->Server
如果server连不上,Client只会占用一个句柄,不管Client发起了多少个连接。
java 12827 oms 6u sock 0,0 168883381 can't identify protocol
如果server连上了,Client每次连接只要不关闭就会一直占用一个句柄,lsof结果如下:
java 11544 oms 113u IPv4 168861112 TCP TEST3050:35686->10.1.24.147:8888 (ESTABLISHED)
java 11544 oms 114u IPv4 168862353 TCP TEST3050:35687->10.1.24.147:8888 (ESTABLISHED)
如果此时Server端进程杀掉,Client端lsof结果如下:
java 11544 oms 180u sock 0,0 168845122 can't identify protocol
java 11544 oms 181u sock 0,0 168845124 can't identify protocol
由于client没有关闭socket,导致连接泄漏。
如果去掉B处的注释,即使不去掉I处的注释,客户端的句柄也都释放了。