This program uses primarily the Socket class. The class TcpSock was built around the Socket class to add ease and functionality.
To start the program you must initialize the Server socket. As you can see, the statement "Server.blocking = false" tells the socket not to block. After initializing the Server socket and binding it to an IP address and port number, the socket is ready to Listen. Now comes the main loop. The first thing we need to check for are incoming connections. Use the Poll method along with the SelectRead argument to do this. When this returns true, we know there is a client trying to connect. So the next thing to do is Accept the connection.
After we have accepted a connection, we can send and receive data. To send the data we simply use the Send method. Receiving data is the hard part. First, we again use the Poll method to check for data available to read. If it returns true, then we call the Recv method, which receives a chunk of data. Telnet does not echo the data unless specifically set to do so, so we will echo the data for telnet. Next we check to see if the person pressed enter... This is this critical part, because we need to know when they have entered a complete line of text, not just a few characters. Once we know they pressed enter, we can send the data to all the other clients using a for loop and the Send method. It's pretty straight- forward.
Lastly, we must close the socket if they disconnect. We already have the information we need. When we Polled the Socket, it returns the number of bytes received. If the number of bytes received = 0, then the Client closed his end of the connection. Now we close our end with the Shutdown and Close methods. Finally, we remove the instance of the TcpSock class from Client, our dynamic array.
This chat program is just a very simple example. If you were ambitious you could add names, commands, and adminstrators.
using System; using System.Collections; using System.Net; using System.Net.Sockets; using System.Text; namespace TcpSock { class TcpSock { int tcpIndx = 0; int tcpByte = 0; byte[] tcpRecv = new byte[1024]; //////////////////////////////////////// public Socket tcpSock; //////////////////////////////////////// public int Recv (ref string tcpRead) { tcpByte = tcpSock.Available; if (tcpByte > tcpRecv.Length - tcpIndx) tcpByte = tcpRecv.Length - tcpIndx; tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte, SocketFlags.Partial); tcpRead = Encoding.ASCII.GetString (tcpRecv, tcpIndx, tcpByte); tcpIndx+= tcpByte; return tcpRead.Length; } public int RecvLn(ref string tcpRead) { tcpRead = Encoding.ASCII.GetString (tcpRecv, 0, tcpIndx); tcpIndx = 0; return tcpRead.Length; } public int Send (string tcpWrite) { return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite)); } public int SendLn(string tcpWrite) { return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n")); } } class Tcp { [STAThread] static void Main() { //////////////////////////////////////////////////////////////////////////////////////////// ///class IPHostEntry : Stores information about the Host and is required ///for IPEndPoint. ///class IPEndPoint : Stores information about the Host IP Address and ///the Port number. ///class TcpSock : Invokes the constructor and creates an instance. ///class ArrayList : Stores a dynamic array of Client TcpSock objects. IPHostEntry Iphe = Dns.Resolve (Dns.GetHostName()); IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444); Socket Server = new Socket (Ipep.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); //////////////////////////////////////////////////////////////////////////////////////////// ///Initialize ///Capacity : Maximux number of clients able to connect. ///Blocking : Determines if the Server TcpSock will stop code execution ///to receive data from the Client TcpSock. ///Bind : Binds the Server TcpSock to the Host IP Address and the Port Number. ///Listen : Begin listening to the Port; it is now ready to accept connections. ArrayList Client = new ArrayList (); string rln = null; Client.Capacity = 256; Server.Blocking = false; Server.Bind (Ipep); Server.Listen( 32 ); Console.WriteLine("{0}: listening to port {1}", Dns.GetHostName(), Ipep.Port); //////////////////////////////////////////////////////////////////////////////////////////// ///Main loop ///1. Poll the Server TcpSock; if true then accept the new connection. ///2. Poll the Client TcpSock; if true then receive data from Clients. while (true) { //Accept if (Server.Poll(0, SelectMode.SelectRead)) { int i = Client.Add(new TcpSock()); ((TcpSock)Client[i]).tcpSock = Server.Accept (); ((TcpSock)Client[i]).SendLn("Welcome."); Console.WriteLine("Client {0} connected.", i ); } for (int i = 0; i < Client.Count; i++) { //check for incoming data if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead)) { //receive incoming data if (((TcpSock)Client[i]).Recv(ref rln) > 0) { //echo incoming data ((TcpSock)Client[i]).Send(rln); //check for new line if (rln == "\r\n") { ///receive line ((TcpSock)Client[i]).RecvLn(ref rln); //send the line to all clients for (int y = 0; y < Client.Count; y++) if (y != i) ((TcpSock)Client[y]).Send(i.ToString() + ": " + rln); Console.Write("{0}: {1}", i, rln); } } //recv returned <= 0; close the socket else { ((TcpSock)Client[i]).tcpSock.Shutdown(SocketShutdown.Both); ((TcpSock)Client[i]).tcpSock.Close(); Client.RemoveAt (i); Console.WriteLine("Client {0} disconnected.", i); } } } } } } } |
No comments:
Post a Comment