一个简单的自定义通信协议(socket)
来源:互联网 发布:淘宝数据插件 编辑:程序博客网 时间:2024/06/05 13:22
转自:http://vtrtbb.javaeye.com/blog/849336
这是转自javaeye的一篇文章,作者是vtrtbb。
按照网络通信的传统,我们都会自定义协议,这有很多好处,大家可以自己体会(嘿嘿)。
一直不知道socket通信时候自定义数据包是什么样子的,偶然做了个小例子。
先来说说数据包的定义,我这里是包头+内容 组成的:其中包头内容分为包类型+包长度, 那就是 消息对象=包类型+包长度+消息体
包类型 byte 型
包长度 int 型
消息体 byte[]
包总长度为 1 + 4 + 消息体.getBytes().length
发包方法如下:
- private void sendTextMsg(DataOutputStream out,String msg ) throws IOException { byte[] bytes= msg.getBytes(); int totalLen = 1 + 4 + bytes.length; out.writeByte(1); out.writeInt(totalLen); out.write(bytes); out.flush(); }
客户端发送消息类为:
- import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class MsgClient { private DataOutputStream outs; public static void main(String[] args) { try { MsgClient client = new MsgClient(); client.connServer("127.0.0.1", 9292); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void sendTextMsg(DataOutputStream out,String msg ) throws IOException { byte[] bytes= msg.getBytes(); int totalLen = 1 + 4 + bytes.length; out.writeByte(1); out.writeInt(totalLen); out.write(bytes); out.flush(); } public void connServer(String ip,int port) throws UnknownHostException, IOException { Socket client = new Socket(ip,port); InputStream in = client.getInputStream(); OutputStream out = client.getOutputStream(); outs = new DataOutputStream(out); while(true) { Scanner scaner = new Scanner(System.in); sendTextMsg(outs, "测试消"); } }
服务端接收类为:
- import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class MsgServer { public static void main(String[] args) { try { MsgServer server = new MsgServer(); server.setUpServer(9090); } catch (IOException e) { e.printStackTrace(); } } public void setUpServer(int port) throws IOException { ServerSocket server = new ServerSocket(port); while(true) { Socket client = server.accept(); System.out.println("客户端IP:"+client.getRemoteSocketAddress()); processMesage(client); } } private void processMesage(Socket client) throws IOException { InputStream ins = client.getInputStream(); DataInputStream dins = new DataInputStream(ins); //服务端解包过程 while(true) { int totalLen = dins.readInt(); byte flag = dins.readByte(); System.out.println("接收消息类型"+flag); byte[] data = new byte[totalLen - 4 - 1]; dins.readFully(data); String msg = new String(data); System.out.println("发来的内容是:"+msg); } } }
这样就基本完成了,但实际还有好多问题,比如说服务端用如何用多线程服务来完成客户端的请求已提高效率,如果是NIO方式怎么来实现?多个消息类型时候怎么抽象?这些都没有考虑
另外有两个开源的框架不错,一个是apache mina 还有个是netty ,有机会试试。
另一篇文章中叙述:
------------------
TCP Socket协议定义
------------------
本文从这里开始,主要介绍TCP的socket编程。
新手们(例如当初的我),第一次写socket,总是以为在发送方压入一个"Helloworld",接收方收到了这个字符串,就“精通”了Socket编程了。而实际上,这种编程根本不可能用在现实项目,因为:
1. socket在传输过程中,helloworld有可能被拆分了,分段到达客户端),例如 hello + world,一个分段就是一个包(Package),这个就是分包问题。
2. socket在传输过成功,不同时间发送的数据包有可能被合并,同时到达了客户端,这个就是黏包问题。例如发送方发送了hello+world,而接收方可能一次就接受了helloworld.
3. socket会自动在每个包后面补n个 0x0 byte,分割包。具体怎么去补,这个我就没有深入了解。
4. 不同的数据类型转化为byte的长度是不同的,例如int转为byte是4位(int32),这样我们在制作socket协议的时候要特别小心了。具体可以使用以下代码去测试:
代码 public void test() { int myInt = 1; byte[] bytes = new byte[1024]; BinaryWriter writer = new BinaryWriter(new MemoryStream(bytes)); writer.Write(myInt); writer.Write("j"); writer.Close();- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 一个简单的自定义通信协议(socket)
- 设计一个简单的socket通信协议
- 一个简单的TCP自定义通信协议
- 自定义Socket通信协议
- 简单高效可靠的自定义通信协议(传输协议)
- socket编程里,如何设计自定义通信协议的包头?
- socket编程里,如何设计自定义通信协议的包头?
- 基于socket简单通信协议实现
- js特效炫丽选项卡01
- 获取字符串
- taskset
- 合并两个动态数组并排序
- 16进制转二进制
- 一个简单的自定义通信协议(socket)
- 网络上的数据报侦听
- jeecms导入myeclipse问题
- shell编程测试文件类型
- UVa 101 - The Blocks Problem
- Socket中接受tcp数据包,怎么让他receive的时候,就接一个数据包?
- 用java实现数组的循环逐步移位操作
- 利用mkfs.ubifs和ubinize两个工具制作UBI镜像
- NBU驱动器的状态总览及异常处理