先开启服务端,再开启客户端,否则Connection refused
如果客户端没有发送结束标识,如socket.shutdownOutput()或者socket.close(),服务端读取数据Connection reset,反之亦然
客户端Client的时候, 如果存在网络问题, 为了避免网络问题,造成客户端长时间等待, 此时要设置一个TimeOut
clientSocket = new Socket();
//这个TimeOut是连接等待时间
clientSocket.connect(tcpAddress, timeOut);
- 当客户端已经连接, 每次收到一个数据, 客户端将启动处理, 假如服务器长久不发数据, 此时客户端会阻塞等待, 为了避免这个时候的等待, 可以设置一个超时
clientSocket.setSoTimeout(timeOut);
如何告知对方已发送完命令
socket 关闭
socket.close()
socket.shutdownOutput()
而不是outputStream.close() (outputStream为发送消息到服务端打开的输出流)):
outputStream.close();
如果关闭了输出流,那么相应的Socket也将关闭,和直接关闭Socket一个性质
socket.shutdownOutput()是将客户端输出流关闭,此时,如果服务端有信息返回,则客户端是可以正常接受的,如果没有,直接关闭Socket
- 不能再次发送消息给服务端,如果再次发送,需要重新建立Socket连接
通过约定符号
双方约定一个字符或者一个短语,来当做消息发送完成的标识,通常这么做就需要改造读取方法
假如约定单端的一行为end,代表发送完成,例如下面的消息,end则代表消息发送完成:
hello wakala
end
服务端读取操作:
Socket socket = server.accept();
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
BufferedReader read=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
String line;
StringBuilder sb = new StringBuilder();
while ((line = read.readLine()) != null && "end".equals(line)) {
//注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(line);
}
通过指定长度
记录异常:Connection reset
当客户端用readLine读取数据时,readline()方法会读到流结束或者\n的时候返回
客户端:
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,DEFAULT));
StringBuilder builder = new StringBuilder();
String line = bufferedReader.readLine();
builder.append(line);
服务端:
String linebreak = System.getProperty("line.separator","\n");
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("response");
// bufferedWriter.write(linebreak);//添加换行符
bufferedWriter.flush();
服务端如果不关闭输出流或者在消息的结尾没有发送换行符\n时,客户端会报Connection reset
如果消息加了换行符,并且服务端没有关闭,在客户端读取时,这样写同样会报错:
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine())!= null){
builder.append(line);
}
//因为 第一次bufferedReader.readLine()已经读完,socket连接已经释放,再次在while()中读取就会 //Connection reset
// 所以去掉while循环,
StringBuilder builder = new StringBuilder();
String line = bufferedReader.readLine();
builder.append(line);
还有:
//客户端这种方式读取,服务端不需要加换行符号
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes))!= - 1){
String part = new String(bytes,0,len,DEFAULT);
//println("result part=="+part);
sb.append(part);
}
客户端一直读取也会报Connection reset
解决方法:
判断inputStream.available()方法,这种方法在读写操作前先得知数据流里有多少个字节可以读取
byte[] bytes = new byte[1024];
do{
len = inputStream.read(bytes);
if (len!=-1){
String sss = new String(bytes,0,len,DEFAULT);
println("result part=="+sss);
sb.append(sss);
}
}while(inputStream.available()!= 0);