java socket 粘包解决_java socket解决半包、粘包问题

本文介绍如何使用Java解决Socket通信中的粘包和半包问题。通过在发送数据时添加包头(包含包体长度)来辅助接收方进行正确拆包。示例代码包括客户端和服务器端实现,分别演示了发送和接收带有包头的完整数据包的过程。
摘要由CSDN通过智能技术生成

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();

}

}

}

}

}

结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值