客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class SocketTest {
int port=3002;
Socket clientSocket;
String ip;
InputStream input;
OutputStream output;
BufferedReader reader;
PrintWriter writer;
public SocketTest() throws UnknownHostException, IOException {
ip="192.168.1.104";
clientSocket=new Socket(InetAddress.getByName(ip), port);
input=clientSocket.getInputStream();
output=clientSocket.getOutputStream();
reader=new BufferedReader(new InputStreamReader(input));
writer=new PrintWriter(new OutputStreamWriter(output));
}
public void send(String data) throws IOException{
writer.write(data);
writer.flush();
String reply=reader.readLine();
System.out.println(reply);
}
public void close() throws IOException{
clientSocket.close();
}
}
服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServerTest {
int port=3002;
ServerSocket server;
Socket clientSocket;
InputStream input;
OutputStream output;
BufferedReader reader;
PrintWriter writer;
public SocketServerTest() throws IOException {
server=new ServerSocket(port);
}
public void service() throws IOException{
while(true){
clientSocket=server.accept();
input=clientSocket.getInputStream();
output=clientSocket.getOutputStream();
reader=new BufferedReader(new InputStreamReader(input));
writer=new PrintWriter(new OutputStreamWriter(output));
while(true){
String receiveStr=reader.readLine();
System.out.println(receiveStr);
writer.write("ok");
writer.flush();
}
}
}
}
运行之后会发现,客户端和服务器端都阻塞在 String receiveStr=reader.readLine();
原因是: 客户端和服务端都有阻塞式方法readLine(),这些方法没有读到结束标记,那么就一直等,而导致两端,都在等待。
这样之后,客户端socket关闭之后,reader.readLine();得到一直未null
解决方式:
1、 读写流是否能读取到结束标记
读写流中的阻塞式方法read和write要刷新缓冲区和加入结束标记,readLine要进行换行操作,以便加入结束标记。
可以使用printReaader 和printWriter 来替代,有自动刷新和换行,这样简化了书写。
2、服务端是否能够接收到客户端结束标记
客户端上传完文件之后,需要向服务端提供一个结束标记。否则虽然客户端的循环结束,还会向下执行,又开始读取服务端反馈的信息,
但是,服务端还没有反馈时,客户端就向下执行了,以至于两端都阻塞。
3、自定义标签可能出现在文本中,所以导致文本文件还读取完就结束,所以使用通用的解决方案:shutDownOutput( )
即可以每次发送数据,writer.write("ok\r\n"); 加上回车标记,reader=new BufferedReader(new InputStreamReader(input));来
读取readline的时候才知道读取结束