java socket解決半包、粘包問題
package org.weir.socket.socketPackage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTest {
public static void main(String[] args) throws IOException, InterruptedException{
new SocketServer().start();
new SocketClient().start();
}
static class SocketClient extends Thread{
Socket clientSocket = new Socket();
public SocketClient() throws IOException{
clientSocket.connect(new InetSocketAddress(8089));
}
public void run(){
String reqMessage = "HelloWorld! from clientsocket this is test half packages!";
try {
for( int i=0;i<10;i++){
OutputStream os = clientSocket.getOutputStream();
os.write(reqMessage.getBytes());
System.out.println("send message "+i+" "+reqMessage);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if (clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
static class SocketServer extends Thread{
ServerSocket serverSocket;
public SocketServer(){
try {
serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8089));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run(){
int count = 0;
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(true){
try {
byte[] byteBuffer = new byte[50];
StringBuffer receivBuffer = new StringBuffer();
InputStream reader = socket.getInputStream();
count = reader.read(byteBuffer);
if(count>0){
receivBuffer.append(new String(byteBuffer,0,count));
System.out.println("receive data from client:"+receivBuffer.toString());
}
count = 0;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package org.weir.socket.socketPackage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
/**
* socket解決半包問題 採用包體長度(兩字節)+包體內容來拆包
* @author weir
* 2017年9月19日下午4:31:36
*/
public class ClientSocket {
public static void main(String args[]) throws IOException {
Socket clientSocket = new Socket();
clientSocket.connect(new InetSocketAddress(8089));
new SendThread(clientSocket).start();
}
static class SendThread extends Thread {
Socket socket;
PrintWriter printWriter = null;
public SendThread(Socket socket) {
this.socket = socket;
try {
printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
String reqMessage = "HelloWorld! from clientsocket this is test half packages!";
for (int i = 0; i < 100; i++) {
sendPacket(reqMessage);
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void sendPacket(String message) {
// byte[] contentBytes = message.getBytes();// 包體內容
// int contentlength = contentBytes.length;// 包體長度
// String head = String.valueOf(contentlength);// 頭部內容
// byte[] headbytes = head.getBytes();// 頭部內容字節數組
// byte[] bytes = new byte[headbytes.length + contentlength];// 包=包頭+包體
// int i = 0;
// for (i = 0; i < headbytes.length; i++) {// 包頭
// bytes[i] = headbytes[i];
// }
// for (int j = i, k = 0; k < contentlength; k++, j++) {// 包體
// bytes[j] = contentBytes[k];
// }
try {
OutputStream writer = socket.getOutputStream();
// writer.write(bytes);
writer.write(message.getBytes());
writer.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package org.weir.socket.socketPackage;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
/*
* packet=packetHead+content
* 先讀出包體長度,再讀出包體,不夠就一直讀
*/
public class SocketServer {
public static void main(String args[]) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8089));
while (true) {
Socket socket = serverSocket.accept();
new ReceiveThread(socket).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class ReceiveThread extends Thread {
public static final int PACKET_HEAD_LENGTH=2;//包頭長度
private Socket socket;
private volatile byte[] bytes = new byte[0];
public ReceiveThread(Socket socket) {
this.socket = socket;
}
public byte[] mergebyte(byte[] a, byte[] b, int begin, int end) {
byte[] add = new byte[a.length + end - begin];
int i = 0;
for (i = 0; i < a.length; i++) {
add[i] = a[i];
}
for (int k = begin; k < end; k++, i++) {
add[i] = b[k];
}
return add;
}
@Override
public void run() {
int count =0;
while (true) {
try {
InputStream reader = socket.getInputStream();
if (bytes.length < PACKET_HEAD_LENGTH) {
byte[] head = new byte[PACKET_HEAD_LENGTH - bytes.length];
int couter = reader.read(head);
if (couter < 0) {
continue;
}
bytes = mergebyte(bytes, head, 0, couter);
if (couter < PACKET_HEAD_LENGTH) {
continue;
}
}
// 下面這個值請注意,一定要取2長度的字節子數組作爲報文長度,你懂得
byte[] temp = new byte[0];
temp = mergebyte(temp, bytes, 0, PACKET_HEAD_LENGTH);
String templength = new String(temp);
int bodylength = Integer.parseInt(templength);//包體長度
if (bytes.length - PACKET_HEAD_LENGTH < bodylength) {//不夠一個包
byte[] body = new byte[bodylength + PACKET_HEAD_LENGTH - bytes.length];//剩下應該讀的字節(湊一個包)
int couter = reader.read(body);
if (couter < 0) {
continue;
}
bytes = mergebyte(bytes, body, 0, couter);
if (couter < body.length) {
continue;
}
}
byte[] body = new byte[0];
body = mergebyte(body, bytes, PACKET_HEAD_LENGTH, bytes.length);
count++;
System.out.println("server receive body: " + count+new String(body));
bytes = new byte[0];
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
結果如下: