c#异步通讯的例子

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

c#异步通讯的例子的相关文章

ajax异步通讯 遮罩滚动栏,防止并发及误操作

加入滚动栏的遮罩,滚动栏图片须要自己调整路径 function loading() { var divloading = "<div id=\"loadingdiv\" style=\"width:100%;height:100%;position:absolute;margin:auto;display:table;padding:auto;background-color:#EBEBEB;opacity:0.7;filter:alpha(Opacity=7

boost_asio学习笔记[2] - 客户端异步通讯

使用boost::asio实现客户端的异步通讯访问pop3服务器. #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> using namespace std; using boost::asio::ip::tcp; #define MAIL_SERVER "pop3.m.com" // 邮件服务器域名 // pop3命令 #define CMD_USER  

串行通讯协议--起止式异步通讯协议(UART)

起止式异步通讯协议: 特点与格式: 起止式异步协议的特点是一个字符一个字符传输,并且传送一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求.其格式如图3 所示.每一个字符的前面都有一位起始位(低电平,逻辑值0),字符本身有5-7位数据位组成,接着字符后面是一位校验位(也可以没有校验位),最后是一 位,或意味半,或二位停止位,停止位后面是不定长度的空闲位.停止位和空闲位都规定为高电平(逻辑值),这样就保证起始位开始处一定有一个下跳沿. 从图中可以看出,这种格式是靠起始位和停止位

企业服务总线之双工异步通讯机

为达到系统的高可靠性.高可用性以及并发处理能力,我们常常采用一些负载均衡的设备(如F5)等进行集群方案.但是,也会存在一些特殊的情况,比如长连接.特殊的技术协议等,不适用于采用F5等设备来解决,双工异步通讯机充当了软F5的作用. 双工异步通讯机的架构如下: 双工异步通讯机根据部署架构情况,即可支持"上行"也可支持"下行".其主要功能是双工异步.负载均衡.故障探测隔离.双机热备(心跳)等.上行通讯机和[email protected]配合主要用于双工异步接入ESB,起

TCP/IP异步通讯服务端实现方法

近期做了个TCP/IP异步通讯服务端实现方法,也是在网上胡乱搜索,然找了个自认为比较好的,然后封装一下,供后面自个使用,也供大家参考,如有不好的地方,欢迎指正,谢谢! 下面说一下这个方法里面的几个知识点: 1.托管 这个东西真心好用,虽然不知道具体怎么弄的,托管可以实现一个对象中的方法交由其他对象实现,而且可以同时触发多个方法,组件的触发函数就是由托管实现的,具体实现如下: 先声明一个托管的方法类型 public delegate void RecieveMsg(string IP_addr,

2018-06-25 js表单事件、三个高度和Ajax异步通讯技术

表单事件: onfocus -> 表单控件得到焦点时触发: obj_ipt.onfocus=function(){}; onblur -> 表单控件失去焦点时: onchange -> 表单控件内容被改变时: onselect -> 控件被选择时: onsubmit -> 当表单提交时: onreset -> 当表单重置时: 表单对象方法: select() -> 对象被选中: ipt_obj.select(); blur() -> 失去焦点 focus()

详解同步通讯和异步通讯的原理

5.1.3 同步通信和异步通信 一.同步通信和异步通信 串行通信可以分为两种类型,一种叫同步通信,另一种叫异步通信. 同步通信方式,是把许多字符组成一个信息组,这样,字符可以一个接一个地传输,但是,在每组信息(通常称为信息帧)的开始要加上同步字符,在没有信息要传 输时,要填上空字符,因为同步传输不允许有间隙.同步方式下,发送方除了发送数据,还要传输同步时钟信号,信息传输的双方用同一个时钟信号确定传输过程中 每1位的位置.见右图5.2所示. 图5.2 同步通信示意图 在异步通信方式中,两个数据字符

ajax 异步 通信 小例子 servlet与 jsp异步

get  请求参数通过 url那里写进去,然后send(null) html文件和 servlet进行通信 通过ajax 进行通信 1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2 <html> 3 <head> 4 <meta http-equiv="

.net平台下socket异步通讯

1,首先添加两个windows窗体项目,一个作为服务端server,一个作为客户端Client 2,然后添加服务端代码,添加命名空间,界面上添加TextBox控件 using System.Net; using System.Net.Sockets; 3,FormLoad方法添加代码 private void Form1_Load(object sender, EventArgs e) { IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(