这是一个简单的c#异步通讯的例子(只有客户端哦)
- C# 异步通讯
- 自定义数据头
- protobuf
- 数据缓冲,解包
代码伺候:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; using ProtoBuf; namespace ProtobufExample { class Program { static byte[] buffer = new byte[1024]; static int writeIndex = 0; static int readIndex = 0; private static Packet current; private static TcpClient client; private static NetworkStream networkStream; static void Main(string[] args) { IPAddress address=new IPAddress(new byte[]{127,0,0,1}); Int32 port=8000; client = new TcpClient(); client.BeginConnect(address,port,new AsyncCallback(ConnectCallback),client); while (true) { if (networkStream != null) { write(client); } Thread.Sleep(100); } } public static void ConnectCallback(IAsyncResult result) { TcpClient client=(TcpClient)result.AsyncState; client.EndConnect(result); networkStream = client.GetStream(); read(client); } private static void write(TcpClient client) { //发送请求游戏服列表协议 Packet packet = new Packet(); packet.Header.Pid = 10001; byte[] data=new byte[PacketHeader.header_size]; packet.Header.serialize(data,0); networkStream.BeginWrite(data, 0, data.Length, new AsyncCallback(WriteCallback), networkStream); } public static void WriteCallback(IAsyncResult result) { NetworkStream networkStream = (NetworkStream)result.AsyncState; networkStream.EndWrite(result); Console.WriteLine("数据包已发送"); } public static void read(TcpClient client) { NetworkStream networkStream=client.GetStream(); networkStream.BeginRead(buffer, writeIndex, buffer.Length - writeIndex, new AsyncCallback(ReadCallback), networkStream); } public static void ReadCallback(IAsyncResult result) { NetworkStream networkStream = (NetworkStream)result.AsyncState; int readbytes=networkStream.EndRead(result); writeIndex += readbytes; Console.WriteLine("读取字节数:"+readbytes); Packet packet = null; while ((packet = readPacket())!=null) { Console.WriteLine("收到协议:" + packet.Header.Pid); MemoryStream ms = new MemoryStream(packet.Content); ServerListResp resp=Serializer.Deserialize<ServerListResp>(ms); Console.WriteLine("服务器列表:" + resp.servers.Count); } networkStream.BeginRead(buffer, writeIndex, buffer.Length - writeIndex, new AsyncCallback(ReadCallback), networkStream); } public static Packet readPacket() { if (PacketHeader.header_size > writeIndex - readIndex) { return null; } if (current == null) { current = new Packet(); } Packet temp = current; temp.Header.deserialize(buffer, readIndex); readIndex += PacketHeader.header_size; if (temp.Header.BodyLength > writeIndex - readIndex) { return null; } byte[] data = new byte[temp.Header.BodyLength]; Array.Copy(buffer,readIndex,data,0,temp.Header.BodyLength); temp.Content = data; readIndex += temp.Header.BodyLength; discardReadBytes(); return temp; } private static void discardReadBytes() { if (readIndex == writeIndex) { writeIndex =0; readIndex = writeIndex; } else { int remaining = writeIndex - readIndex; byte[] temp = new byte[remaining]; Array.Copy(buffer, readIndex, temp, 0, remaining); writeIndex = remaining; readIndex = 0; Array.Copy(temp,buffer, remaining); } } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ProtobufExample { class PacketHeader { public static int header_size = 6; private int pid; private int code; private int bodyLength; public void deserialize(byte[] src,int offset) { this.code = src[offset] <<8|src[offset+1]; this.pid = src[offset+2] << 8 | src[offset + 3]; this.bodyLength = src[offset+4] << 8 | src[offset + 5]; } public void serialize(byte[] dist,int offset) { dist[offset]=(byte)(this.code>>8&0xff); dist[offset+1] = (byte)(this.code & 0xff); dist[offset + 2] = (byte)(this.pid >> 8 & 0xff); dist[offset + 3] = (byte)(this.pid & 0xff); dist[offset + 4] = (byte)(this.bodyLength >> 8 & 0xff); dist[offset + 5] = (byte)(this.bodyLength & 0xff); } public int BodyLength { get{return bodyLength;} set{this.bodyLength=value;} } public int Pid { get { return pid; } set { this.pid = value; } } } class Packet { private PacketHeader header; private byte[] content; public PacketHeader Header { get { if(header==null) { header=new PacketHeader(); } return header; } set { this.header=value; } } public byte[] Content { get { return content; } set { this.content = value; } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ProtoBuf; namespace ProtobufExample { [ProtoContract] class ServerListResp { [ProtoMember(1)] public List<Server> servers { get; set; } } [ProtoContract] class Server { [ProtoMember(1)] public Int32 serverId {get;set;} [ProtoMember(2)] public string serverName { get; set; } [ProtoMember(3)] public Int32 serverStatus { get; set; } [ProtoMember(4)] public Int32 serverLabel { get; set; } } }
时间: 2024-10-17 05:56:35