绑定时 C# 异步 SocketException

Posted

技术标签:

【中文标题】绑定时 C# 异步 SocketException【英文标题】:C# async SocketException while binding 【发布时间】:2015-01-25 16:09:29 【问题描述】:

我正在使用异步套接字在 C# 上开发客户端-服务器应用程序。当我监听连接时,我不断收到此错误

“System.Net.Sockets.SocketException”类型的未处理异常 发生在 System.dll 中

附加信息:每个套接字地址(协议/网络地址/端口)通常只允许使用一次

这是发生此异常的行:

 _listener.Bind(new IPEndPoint(0, port));

代码在Listener.Start(int port) 下。在主程序中,我是这样调用方法的:

void btnListen_Click(object sender, EventArgs e)
        
            _listener = new Listener();
            _listener.Accepted += new Listener.SocketAcceptedHandler(listener_Accepted);
            _listener.Start(8192);
        

我正在我的 PC 中测试客户端和服务器应用程序。

这是Listener 类。

namespace serverPC

    class Listener
    
        public delegate void SocketAcceptedHandler(Socket e);
        public event SocketAcceptedHandler Accepted;

        Socket _listener;
        public int Port;

        public bool Running
        
            get;
            private set;
        

        public Listener() Port = 0;

        public void Start(int port)
        
            if (Running)
                return;

            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _listener.Bind(new IPEndPoint(0, port)); // This is where the SocketException error occurs
            _listener.Listen(0);

            _listener.BeginAccept(acceptedCallback, null);
            Running = true;
        

        public void Stop()
        
            if (!Running)
                return;

            _listener.Close();
            Running = false;
        

        void acceptedCallback(IAsyncResult ar)
        
            try
            
                Socket s = _listener.EndAccept(ar);

                if (Accepted != null)
                
                    Accepted(s);
                
            
            catch
            

            

            if (Running)
            
                try
                
                    _listener.BeginAccept(acceptedCallback, null);
                
                catch
                

                
            
        
    
    

这是Client 类。

namespace serverPC

    struct ReceiveBuffer
    
        public const int BUFFER_SIZE = 1024;
        public byte[] Buffer;
        public int ToReceive;
        public MemoryStream BufStream;
  
        public ReceiveBuffer(int toRec)
        
            Buffer = new byte[BUFFER_SIZE];
            ToReceive = toRec;
            BufStream = new MemoryStream(toRec);
        

        public void Dispose()
        
            Buffer = null;
            ToReceive = 0;
            Close();
            if (BufStream != null)
                BufStream.Dispose();
        

        public void Close()
        
            if (BufStream != null && BufStream.CanWrite)
            
                BufStream.Close();
            
        
    

    class Client
    
        byte[] lenBuffer;
        ReceiveBuffer buffer;
        Socket _socket;

        public IPEndPoint EndPoint
        
            get
            
                if (_socket != null && _socket.Connected)
                
                    return (IPEndPoint)_socket.RemoteEndPoint;
                

                return new IPEndPoint(IPAddress.None, 0);
            
        

        public delegate void DisconnectedEventHandler(Client sender);
        public event DisconnectedEventHandler Disconnected;
        public delegate void DataReceivedEventHandler(Client sender, ReceiveBuffer e);
        public event DataReceivedEventHandler DataReceived;

        public Client(Socket s)
        
            _socket = s;
            lenBuffer = new byte[4];
        

        public void Close()
        
            if (_socket != null)
            
                _socket.Disconnect(false);
                _socket.Close();
            

            buffer.Dispose();
            _socket = null;
            lenBuffer = null;
            Disconnected = null;
            DataReceived = null;
        

        public void ReceiveAsync()
        
            _socket.BeginReceive(lenBuffer, 0, lenBuffer.Length, SocketFlags.None, receiveCallback, null);
        

        void receiveCallback(IAsyncResult ar)
         
            try
            
                int rec = _socket.EndReceive(ar);

                if (rec == 0)
                
                    if (Disconnected != null)
                    
                        Disconnected(this);
                        return;
                    

                    if (rec != 4)
                    
                        throw new Exception();
                    
                
            

            catch (SocketException se)
            
                switch (se.SocketErrorCode)
                
                    case SocketError.ConnectionAborted:
                    case SocketError.ConnectionReset:
                        if (Disconnected != null)
                        
                            Disconnected(this);
                            return;
                        
                        break;
                
            
            catch (ObjectDisposedException)
            
                return;
            
            catch (NullReferenceException)
            
                return;
            
            catch (Exception ex)
            
                Console.WriteLine(ex.Message);
                return;
            

            buffer = new ReceiveBuffer(BitConverter.ToInt32(lenBuffer, 0));

            _socket.BeginReceive(buffer.Buffer, 0, buffer.Buffer.Length, SocketFlags.None, receivePacketCallback, null);

        

        void receivePacketCallback(IAsyncResult ar)
        
            int rec = _socket.EndReceive(ar);

            if (rec <= 0)
            
                return;
            

            buffer.BufStream.Write(buffer.Buffer, 0, rec);

            buffer.ToReceive -= rec;

            if(buffer.ToReceive > 0)
            
                Array.Clear(buffer.Buffer, 0, buffer.Buffer.Length);

                _socket.BeginReceive(buffer.Buffer, 0, buffer.Buffer.Length, SocketFlags.None, receivePacketCallback, null);
                return;
            

            if (DataReceived != null)
            
                buffer.BufStream.Position = 0;
                DataReceived(this, buffer);
            

            buffer.Dispose();

            ReceiveAsync();
        
    

为什么会收到 SocketException 错误?任何帮助表示赞赏。谢谢!

【问题讨论】:

问题解决了吗?找到解决办法了吗? 【参考方案1】:

所以要检查的事情很明显 - 端口 8192 上已经有东西在监听,或者有其他原因导致您的机器拒绝您的程序打开该端口(防火墙等)。

另一个问题是,当您使用“正在运行”检查阻止绑定两次时,您只是为侦听器的实例执行此操作 - 点击按钮将创建一个全新的侦听器并尝试让它在端口 8192 上侦听- 因为你已经绑定了一个监听器,所以会因为那个异常而失败。

【讨论】:

你提到的第一件事没有问题。我的防火墙允许我的应用程序,没有其他东西在监听端口(我已经检查过了)。我不太明白你在这里的意思->“你通过“运行”检查阻止绑定两次,你只是为监听器的实例这样做” 我现在明白你在后半部分的意思了。

以上是关于绑定时 C# 异步 SocketException的主要内容,如果未能解决你的问题,请参考以下文章

c# datagridview 绑定数据时逐行显示并且有进度条。问题如下:

c# 移除类中所有事件的绑定

c# 移除类中所有事件的绑定

C# dataGridView1的函数里 重新绑定的问题

C# 理解阻塞 UI 和异步/等待与 Task.Run 的问题?

Httpclient在.net core3.1上成功运行,但更新到.net 5中连接超时(System.Net.Sockets.SocketException (10060)) C#