【网络通讯】【Socket实现(二)】

网络通讯系列

第五章 【网络通讯】【详细场景下的Demo示例(五)】
第四章 【网络通讯】【DotNetty实现(四)】
第三章 【网络通讯】【SuperSocket实现(三)】
第二章 【网络通讯】【Socket实现(二)】
第一章 【网络通讯】【通讯协议(一)】



前言

介绍使用Socket实现网络通讯。


一、程序设计

不依赖于第三方库,我们使用最原始的Socket来实现上位机客户端。
这一章的目的主要是为了让大家熟悉Socket通讯的原理,后面第三、第四章均是使用开源库实现,也是推荐大家在实际项目中使用的,更加高效、稳定。

要实现客户端,我们需要设计四个接口
分别是连接服务器、断连服务器、发送服务器内容、以及接收服务器内容

其中,接收服务器内容,我们不通过接口实现,而是通过事件通知,因为我们不知道什么时候服务器会发送内容,如果使用接口的话需要多开一个线程不断判断,不太好。

后续优化,在客户端中实现自动断线重连功能、解决连接不存在IP的服务器时时间过长问题(Ping功能)等等,这个会在第五章中的Demo实例中有完整解决方案资源可下载。

二、代码

public class CSocketClient
{
    private Thread? mReceiveThread = null;    //接收数据线程
    private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
    private Socket? __m_hSocket = null;     //Socket句柄
    private int mPort = 0;      //记录本客户端端口号
    private string mIP = "";    //记录本客户端IP地址

    public delegate void ReceiveDataEvent(string ip, int port, byte[] receive);
    public event ReceiveDataEvent? OnReceiveData;   //接收到内容事件通知

    /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="hostAddress"></param>
        /// <param name="nHostPort"></param>
        /// <returns></returns>
    public bool Connect(string hostAddress, int nHostPort)
    {
        DisConnect();
        if (__m_hSocket == null)
        {
            __m_hSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);   //定义一个socket对象 
        }

        try
        {
            mPort = nHostPort;
            mIP = hostAddress;
            IPAddress sin_addr = IPAddress.Parse(hostAddress);
            IPEndPoint endPoint = new IPEndPoint(sin_addr, nHostPort);
            __m_hSocket.Connect(endPoint);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex);
        }

        //开启一个新的线程不停的接收服务端发来的消息  
        mReceiveThread = new Thread(() => OnClientRecvTimer(_cancellationTokenSource.Token));
        mReceiveThread.Name = "SockReceive" + mReceiveThread.ManagedThreadId;
        mReceiveThread.Start();
        return true;
    }

    /// <summary>
        /// 发送服务器数据,字节
        /// </summary>
        /// <param name="sendBuf">要发送的数据</param>
        /// <returns>1:成功  0:失败</returns>
    public byte Send(byte[] sendBuf)
        {
            try
            {
                if (__m_hSocket == null)
                {
                    return 0;
                }

                int sendBufLen = sendBuf.Length;
                int sendRtn = __m_hSocket.Send(sendBuf, sendBufLen, SocketFlags.None);
                sendRtn = __m_hSocket.Send(sendBuf, 0, SocketFlags.None);
                return 1;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
            return 0;
        }

    /// <summary>
        /// 关闭连接
        /// </summary>
    public void DisConnect()
    {
        _cancellationTokenSource.Cancel();
        if (__m_hSocket is null)
        {
            return;
        }
        try
        {
            __m_hSocket.Shutdown(SocketShutdown.Both);
            Thread.Sleep(10);
            __m_hSocket.Close();                          //关闭连接
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex);
        }
    }

    /// <summary>
        /// 接收服务器数据线程
        /// </summary>
        /// <param name="clientSocket"></param>
    private void OnClientRecvTimer(CancellationToken token)
        {
            int recvLen = 0;
            byte[] mReceiveBufRemote = new byte[1024];
            while (!token.IsCancellationRequested)
            {
                Thread.Sleep(1);
                try
                {
                    if (__m_hSocket == null || __m_hSocket.Available <= 0)
                    {
                        continue;
                    }

                    mReceiveBufRemote = new byte[1024];
                    recvLen = __m_hSocket.Receive(mReceiveBufRemote, mReceiveBufRemote.Length, 0);      //接收数据
                    if (recvLen > 0)
                    {
                        recvLen = 0;
                        OnReceiveData?.Invoke(mIP, mPort, mReceiveBufRemote);
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex);
                    Thread.Sleep(100);
                }
            }
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值