博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# Socket学习笔记三
阅读量:5272 次
发布时间:2019-06-14

本文共 5457 字,大约阅读时间需要 18 分钟。

客户端进行异步操作

接收信息及发送信息分开进行,运行多线程进行管理

主要代码发下:

using System;

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

//  实现Socket客户端的连接通信逻辑。

    internal sealed class SocketClient : IDisposable
    {
        //  Socket操作常数。
        private const Int32 ReceiveOperation = 1, SendOperation = 0;
        //  用于发送/接收消息的Socket。
        private Socket clientSocket;
        //  Socket连接标志。
        private Boolean connected = false;
        //  侦听者端点。
        private IPEndPoint hostEndPoint;

        //缓冲区大小

        private int bufferSize = 2048;

        private int ReceiveBufferSize = 2096;

        //  触发连接。

        private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
        //  触发发送/接收操作。
        private static AutoResetEvent autoSendEvent = new AutoResetEvent(false);
        private static AutoResetEvent autoReceiveEvent = new AutoResetEvent(false);
        //private static AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false) };
        //  创建一个未初始化的客户端实例。
        //  启动传送/接收处理将调用Connect方法,然后是SendReceive方法。
        internal SocketClient(String hostName, Int32 port)
        {
            //  获取主机有关的信息。
            IPHostEntry host = Dns.GetHostEntry(hostName);
            //  主机地址。
            IPAddress[] addressList = host.AddressList;
            //  实例化端点和Socket。
            hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
            clientSocket = new Socket(hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }

        //得到连接服务器的状态

        internal bool GetConnectState()
        {
            return connected;
        }

        //  连接主机(同步连接)。

        internal void Connect()
        {
            try
            {
                clientSocket.Connect(hostEndPoint);
                this.connected = true;
            }
            catch (SocketException ex)
            {
                throw new Exception(ex.Message);
            }
          
        }

        //********* 以下为异步连接操作********

        internal void ConnectAsync()
        {
            SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
            connectArgs.UserToken = clientSocket;
            connectArgs.RemoteEndPoint = hostEndPoint;
            connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
            clientSocket.ConnectAsync(connectArgs);
            autoConnectEvent.WaitOne();
            SocketError errorCode = connectArgs.SocketError;
            if (errorCode != SocketError.Success)
            {
                throw new SocketException((Int32)errorCode);
            }
        }

        //  与主机断开连接。

        internal void Disconnect()
        {
            clientSocket.Disconnect(false);
        }

        //  连接操作的回调方法

        private void OnConnect(object sender, SocketAsyncEventArgs e)
        {
            //  发出连接完成信号。
            autoConnectEvent.Set();
            //  设置Socket已连接标志。
            connected = (e.SocketError == SocketError.Success);

        }

        //  接收操作的回调方法
        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            //  发出接收完成信号。
            //autoSendReceiveEvents[ReceiveOperation].Set();
            autoReceiveEvent.Set();

        }

        //  发送操作的回调方法
        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            //  发出发送完成信号。
            //autoSendReceiveEvents[SendOperation].Set();
            autoSendEvent.Set();
            //if (e.SocketError == SocketError.Success)
            //{
            //    if (e.LastOperation == SocketAsyncOperation.Send)
            //    {
            //        //  准备接收。
            //        Socket s = e.UserToken as Socket;
            //        byte[] receiveBuffer = new byte[1024];
            //        e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
            //        e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
            //        s.ReceiveAsync(e);
            //    }
            //}
            //else
            //{
            //    ProcessError(e);
            //}
        }
        //  失败时关闭Socket,根据SocketError抛出异常。
        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s.Connected)
            {
                //  关闭与客户端关联的Socket
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    //  如果客户端处理已经关闭,抛出异常
                }
                finally
                {
                    if (s.Connected)
                    {
                        s.Close();
                    }
                }
            }
            //  抛出SocketException
            throw new SocketException((Int32)e.SocketError);
        }
        //接收消息
        internal string FromHsMessage()
        {
            if (connected)
            {
                //  创建一个接收缓冲区。
                byte[] receiveBuffer = new byte[ReceiveBufferSize];
                //  准备发送/接收操作的参数。
                SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
                completeArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
                completeArgs.UserToken = clientSocket;
                completeArgs.RemoteEndPoint = hostEndPoint;
                completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                //  开始异步接收。
                clientSocket.ReceiveAsync(completeArgs);
                //  等待发送/接收完成。
                autoReceiveEvent.WaitOne();
                //AutoResetEvent.WaitAll(autoSendReceiveEvents);
                //  从SocketAsyncEventArgs缓冲区返回数据.
                return Encoding.UTF8.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);

            }

            else
            {
                throw new SocketException((Int32)SocketError.NotConnected);
            }
        }

        //  与主机交换消息(发送消息)。

        internal String SendMessage(String message)
        {
            if (connected)
            {
                //  创建一个发送缓冲区。
                Byte[] sendBuffer = Encoding.UTF8.GetBytes(message.ToCharArray(), 0, message.ToCharArray().Length);
                //  准备发送/接收操作的参数。
                SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
                completeArgs.SetBuffer(sendBuffer, 0, bufferSize > sendBuffer.Length ? sendBuffer.Length : bufferSize);
                completeArgs.UserToken = clientSocket;
                completeArgs.RemoteEndPoint = hostEndPoint;
                completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
                //  开始异步发送。
                clientSocket.SendAsync(completeArgs);
                //  等待发送/接收完成。
                autoSendEvent.WaitOne();
                //AutoResetEvent.WaitAll(autoSendReceiveEvents);
                //  从SocketAsyncEventArgs缓冲区返回数据.
                return  Encoding.UTF8.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);
            }
            else
            {
                throw new SocketException((Int32)SocketError.NotConnected);
            }
        }

        #region IDisposable Members

        // 释放SocketClient实例。
        public void Dispose()
        {
            autoConnectEvent.Close();
            autoSendEvent.Close();
            autoReceiveEvent.Close();
            //autoSendReceiveEvents[SendOperation].Close();
            //autoSendReceiveEvents[ReceiveOperation].Close();
            if (clientSocket.Connected)
            {
                clientSocket.Close();
            }
        }
        #endregion
    }

转载于:https://www.cnblogs.com/lgSoftLive/archive/2012/12/26/2834004.html

你可能感兴趣的文章
设置dataGridView单元格颜色、字体、ToolTip、字体颜色
查看>>
wx-charts 微信小程序图表 -- radarChart C# .net .ashx 测试
查看>>
对项目重命名
查看>>
Scrapy框架简介及小项目应用
查看>>
tkinter学习三
查看>>
CentOS自带定时任务crontab
查看>>
基因组拼接中常见的名词解释
查看>>
##CS3动画效果
查看>>
nginx 配置 http重定向到https
查看>>
Linux vi/vim
查看>>
JS 设置复选框的选中与取消选中
查看>>
【京东咚咚架构演进】-- 好文收藏
查看>>
【BZOJ 3155】Preprefix sum(树状数组)
查看>>
【洛谷 2430】严酷的训练
查看>>
hadoop 使用java操作hdfs
查看>>
中年男人 中年女人 中年人
查看>>
GoFramework框架简介(三)通信机制篇
查看>>
python全栈学习--day31(正则)
查看>>
h.264语法结构分析
查看>>
基督-神[上帝]的道,真理的本真归回
查看>>