先開啓服務端,再開啓客戶端,否則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);