简体   繁体   中英

C# SocketException when accepting connections

I have been trying to learn about sockets for the past day or so. I thought it would be a good idea to make a basic chat client and server to learn with, I have tried to make an asynchronous server so I don't need to use loads of threads etc and I have came into an issue I simply can't fix. When I start my server, it goes through all ok and waits at the point where it needs to wait for a connection. I then start up my makeshift 'client' that simply sends a string for now and my server crashes with a SocketException with the message

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

I don't see how my socket is not connected when it has to accept the connection in the first place. I have been using this tutorial ( https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx ) as a guide and have looked at both my code and the tutorial and still don't understand what I am doing wrong, can anyone help me?

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;
        }
    }
}

You're never calling EndAccept (from the example you linked):

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

The socket in ar.AsyncState is the listening socket, not the connected client. AsyncState is an arbitrary object you can use to pass information to the callback method ( AcceptConnectionAsync ). In this case, you are passing the serverSocket (the second parameter below):

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

When you call EndAccept on the listening socket, you are getting a new Socket instance that is a specific connection to the client -- your listener socket will start the asynchronous request to accept another connection in your while loop in StartListen . The socket returned by EndAccept is in a connected state and ready to communicate with the other endpoint, based on this specific callback invocation (hence, the requirement to supply IAsyncResult as an argument).

This is referred to as the Asynchronous Programming Model . MSDN has some great information on this (as usual).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM