这是一个简单的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; }

    }
}