/// <summary> /// Starts the server listening for activity on all network interfaces /// </summary> /// <param name="callback">The method to call when a new client has connected</param> /// <param name="port">The port on which to listen.</param> public static void Server_Awaiting_Client_Loop(ConnectionCallBack callback, int port) { //Establish the local address and endpoint. IPAddress localIpAddress = IPAddress.IPv6Any; IPEndPoint localEndPoint = new IPEndPoint(localIpAddress, port); //Create the socket that will listen. Socket listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); //WWO: should this really be IPv6Only? ARen't we likely to get IPv4 data come is as well? //SER: the IPv6Only property is being set to false... listener.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); //Create the state object that will be passed to the new client thread. NetworkState state = new NetworkState(callback, listener); state.ConnectionState = NetworkState.ConnectionStates.DISCONNECTED; state.Buffer = new byte[PACKET_SIZE]; //Bind the endpoint to the socket, and kick off the listening chain. listener.Bind(localEndPoint); //WWO: What is the backlog for? Is this a limit to the number of players that can come in? //SER: My understanding is the backlog is the number of requests we can have before we deal with them listener.Listen(100); listener.BeginAccept(Accept_A_New_Client, state); }
private void BeginConnectCallback(IAsyncResult ar) { s.EndConnect(ar); ConnectionCallBack func = (ConnectionCallBack)ar.AsyncState; func(); }
/// <summary> /// Constructor /// </summary> /// <param name="connectionCallBack">A function to be called on a successful connection</param> /// <param name="socket">Socket referring to this connection</param> /// <param name="id">The ID number of the callback chain to identify unique clients.</param> public NetworkState(ConnectionCallBack connectionCallBack, Socket socket, int id = 0) { this.CallBack = connectionCallBack; this.Socket = socket; this.Buffer = new byte[Network.PACKET_SIZE]; this.ConnectionState = ConnectionStates.DISCONNECTED; this.ID = id; }
/// <summary> /// Method called when the server receives a connection. It adds the /// newly connected socket to the NetworkState, then calls the callback /// specified in ServerAwaitingConnectionLoop /// </summary> public static void Accept_A_New_Client(IAsyncResult ar) { NetworkState state = (NetworkState)ar.AsyncState; Socket oldListener = state.Socket; ConnectionCallBack serverAwaitingClientCallback = state.CallBack; int oldPort = ((IPEndPoint)oldListener.LocalEndPoint).Port; // WWO: Why the distinction between a new socket and the old socket? What if the old socket already has data ready to go? /* SER: It doesn't. This is how you accept a connection from a * client. I think the idea is that this new socket is on a new * port, so that the original port (11000) is still free to accept * connections. */ Socket newConnection = state.Socket.EndAccept(ar); state.ConnectionState = NetworkState.ConnectionStates.CONNECTED; state.Socket = newConnection; // DONE: Not disposing of the old socket would be a resource leak; and would not let us re-use the port, but I don't know the proper procedure. //WWO: I think this is good as far as the procedure, I just don't understand the reasoning behind doing this. /*SER: I have changed the TODO to DONE, since I think it is. You * have to dispose of the old socket so that port 11000 is free * again. The easier solution would be for ServerAwaitingClientLoop * to accept a socket, but that would violate the specification. */ oldListener.Close(); oldListener.Dispose(); state.CallBack(state); // WWO: shouldn't this be a call to newConnection.BeginReceive() ? /*SER: Whatever program is using our library is in charge of using * the sockets; maybe they don't want data yet. That's why we update * the state object and toss it to the callback */ Server_Awaiting_Client_Loop(serverAwaitingClientCallback, oldPort); }
/// <summary> /// Attempts to connect to a server with the given hostname /// </summary> /// <param name="callBack">Function to call when a connection is made</param> /// <param name="hostName">hostname:port to connect to</param> public static Socket ConnectToServer(ConnectionCallBack callBack, string hostName) { //Unpack the name and port from the host name. string serverName = hostName.Split(':')[0]; int port = int.Parse(hostName.Split(':')[1]); //Create the socket. IPAddress serverAddress; if (!IPAddress.TryParse(serverName, out serverAddress)) { IPHostEntry hostEntry = Dns.GetHostEntry(serverName); serverAddress = hostEntry.AddressList[0]; } IPEndPoint ipEndpoint = new IPEndPoint(serverAddress, port); Socket socket = new Socket(ipEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Machnination which will be passed around within this class ferrying data NetworkState state = new NetworkState(callBack, socket); //Begins the connection, but does not wait for it to complete socket.BeginConnect(ipEndpoint.Address, port, ConnectedToServer, state); return(socket); }
public void connect(ConnectionCallBack back) { s.BeginConnect(host, port, new AsyncCallback(BeginConnectCallback), back); }