C#SOCKET异步通信

SOCKET通信是网络软件的基础,服务端SOCKET创建与侦听很容易,客户端SOCKET的创建与连接也很容易,(Send,Receive)同步通信一般只能做为演示和学习理念,实用性不强,通常好的传输系统都采用异步通信(BeginSend,EndSend;BeginReceive,EndReceive),主要内容就是对包的定义,(4个字节来表示整个包的长度,4个字节来表示命令的长度,命令的实际内容,数据内容),接收方在首先接收4个字节,得出整个包的长度(client.BeginReceive(Buffer, 0, 4, socketFlags, new AsyncCallback(ReceivePackHeadCallback), state); )然后在回调函数中接收整个包内容,排除前面的4个字节,client.BeginReceive(Buffer, 4, packetLength - 4, SocketFlags.None, new AsyncCallback(ReceivePackDataCallback), state);在第二次异步接收的回调函数中处理命令和数据。

(关于异步接收的回调时机)以下内容非常重要

引用一段别人的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;


namespace SocketServer
{
    class Program
    {
        //服务端buffer为4字节
        static byte[] buffer = new byte[4];
        static void Main(string[] args)
        {
            Console.WriteLine("[Server]");
            try
            {
                Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketServer.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4444));
                socketServer.Listen(int.MaxValue);
                Console.WriteLine("服务端已启动,等待连接...");
                //接收连接
                Socket ts = socketServer.Accept();
                Console.WriteLine("客户端已连接");


                //开始异步接收
                ts.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), ts);
                Console.ReadKey();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }


        static void ReceiveCallback(IAsyncResult result)
        {
            Socket ts = (Socket)result.AsyncState;
            ts.EndReceive(result);
            result.AsyncWaitHandle.Close();
            Console.WriteLine("收到消息:{0}", Encoding.ASCII.GetString(buffer));


            //清空数据,重新开始异步接收
            buffer = new byte[buffer.Length];
            ts.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), ts);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;


namespace SocketClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("[Client]");
            try
            {
                Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketClient.Connect(IPAddress.Parse("127.0.0.1"), 4444);
                Console.WriteLine("发送消息:");
                //获取发送内容
                string sendStr = Console.ReadLine();
                while (!(sendStr.ToLower() == "q"))
                {
                    Console.WriteLine("发送消息:");
                    //同步发送数据
                      socketClient.Send(Encoding.ASCII.GetBytes(sendStr));
                    sendStr = Console.ReadLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("按任意键退出");
                Console.ReadKey();
            }
        }
    }
}

C#SOCKET异步通信_第1张图片

1.发送数据长度与接收Buffer长度一致,接收到所有数据回调;

2.发送数据长度大于接收Buffer长度,Buffer填满时回调,数据接收完时回调;

3.发送数据长度小于接收Buffer长度,数据接收完时回调;

原文地址: http://www.cnblogs.com/wangtonghui/p/3277303.html

对于这样的小数据,可能大家都这么认为,其实只要接收方一接到数据就会触发回调,不论Buffer有没有填满,千万别认为指定了接收长度就必须接收完才回调

Socket.BeginReceive 方法 (Byte[], offset, size, SocketFlags, AsyncCallback, Object)

https://msdn.microsoft.com/zh-cn/library/dxkwh6zw(v=vs.110).aspx
特别提示:
int bytesRead = client.EndReceive(ar);
在这里,一定要判断接收到的数据长度,是不是接收完了,如果一个包长度为4096个字节,本次的bytesRead为2000个,那就要继续再接收剩余的2096个字节,如果网络延迟,甚至会出现多次接收后才会接收到完整的数据包,然后再在回调函数中解析整个包和写业务逻辑,这个坑我遇见过,切记,血的教训呀。这样就能保证通信稳定可靠!!

你可能感兴趣的:(C#)