接受连接时出现 C# SocketException

C# SocketException when accepting connections

过去一天左右,我一直在尝试了解套接字。我认为制作一个基本的聊天客户端和服务器来学习是个好主意,我已经尝试制作一个异步服务器所以我不需要使用大量线程等我遇到了一个问题我可以修复。当我启动我的服务器时,它一切正常并在需要等待连接的地方等待。然后我启动我的临时 'client',它只是暂时发送一个字符串,我的服务器崩溃并显示消息 SocketException

Additional information: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

当我的套接字首先必须接受连接时,我不明白我的套接字是如何未连接的。我一直在使用本教程 (https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx) 作为指南并查看了我的代码和教程,但仍然不明白我做错了什么,有人可以帮助我吗?

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Chat_Application
{
    class Server
    {
        private Socket serverSocket = null;
        private volatile ArrayList connections = null; // will hold all client sockets
        private const int port = 1090;
        private IPAddress ipAddress = null;
        private IPEndPoint ipEndPoint = null;
        private Thread listenThread = null; // seperate thread to run the server 
        private ManualResetEvent allDone = null;

        public Server()
        {
            this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            this.connections = new ArrayList();
            ipAddress = IPAddress.Parse(GetLocalIPv4(NetworkInterfaceType.Ethernet));
            ipEndPoint = new IPEndPoint(ipAddress, port);
            listenThread = new Thread(StartListen);
            allDone = new ManualResetEvent(false);
        }

        public void Start()
        {
            listenThread.Start();
        }

        public void StartListen()
        {
            this.serverSocket.Bind(ipEndPoint);
            this.serverSocket.Listen(20);
            Program.mainWin.console.Text += "\n<INFO> Socket bound, listening for connections...";

            while (true)
            {
                allDone.Reset();
                serverSocket.BeginAccept(new AsyncCallback(AcceptConnectionAsync), serverSocket);
                Program.mainWin.console.Text += "\n<INFO> Conncetion accepted...";
                allDone.WaitOne();

            }
        }

        public void AcceptConnectionAsync(IAsyncResult AR)
        {
            Byte[] bufferBytes = new byte[1024]; 
            allDone.Set();
            Socket client = (Socket) AR.AsyncState;
            int x = client.Receive(bufferBytes);
            Program.mainWin.console.Text += System.Text.Encoding.Default.GetString(bufferBytes);

        }

        public string GetLocalIPv4(NetworkInterfaceType _type)
        {
            string output = "";
            foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
                {
                    foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            output = ip.Address.ToString();
                        }
                    }
                }
            }
            return output;
        }
    }
}

您永远不会调用 EndAccept(根据您链接的示例):

// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar); // This right here

ar.AsyncState中的套接字是监听套接字,不是连接的客户端。 AsyncState 是一个任意对象,可用于将信息传递给回调方法 (AcceptConnectionAsync)。在这种情况下,您传递的是 serverSocket(下面的第二个参数):

serverSocket.BeginAccept(new AsyncCallback(AcceptConnectionAsync), serverSocket);

当您在侦听套接字上调用 EndAccept 时,您将获得一个 new Socket 实例,它是到客户端的特定连接 -- 您的侦听器套接字将启动异步请求以在 StartListen 中的 while 循环中接受另一个连接。 EndAccept 返回的套接字处于连接状态并准备好与另一个端点通信,基于此特定回调调用(因此,需要提供 IAsyncResult 作为参数)。

这被称为异步编程模型MSDN has some great information 关于这个(像往常一样)。