Problem : You have a situation in which an existing transfer protocol doesn’t
meet your needs. For example, if HTTP is too simplistic, SOAP is too
heavy, RPC is too complex, and you can’t use the Windows Communication
Foundation (WCF), you may need to design your own application-level
protocol on top of TCP/IP.
Solution: .NET makes creating a TCP/IP client and server very easy. Let’s do the server first (see Listing 1). The logic is pretty easy to follow:
Run in a loop. Inside the loop, wait for a connection. Once a connection is achieved, spawn a thread to handle it. Receive a message. Send a response. Close the connection and return from the thread.
Listing.1. TCP Server
using System; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading;
namespace TcpServer { class Program { static void Main(string[] args) { IPAddress localhost = IPAddress.Parse("127.0.0.1"); TcpListener listener = new System.Net.Sockets.TcpListener(localhost, 1330); listener.Start();
while (true) { Console.WriteLine("Waiting for connection"); //AcceptTcpClient waits for a connection from the client TcpClient client = listener.AcceptTcpClient(); //start a new thread to handle this connection so we can //go back to waiting for another client Thread thread = new Thread( new ParameterizedThreadStart(HandleClientThread)); thread.Start(client); } }
static void HandleClientThread(object obj) { TcpClient client = obj as TcpClient; bool done = false; while (!done) { string received = ReadMessage(client); Console.WriteLine("Received: {0}", received); done = received.Equals("bye"); if (done) SendResponse(client, "BYE"); else SendResponse(client, "OK"); } client.Close(); Console.WriteLine("Connection closed"); }
private static string ReadMessage(TcpClient client) { byte[] buffer = new byte[256]; int totalRead = 0; //read bytes until stream indicates there are no more do { int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead); totalRead += read; } while (client.GetStream().DataAvailable);
return Encoding.Unicode.GetString(buffer, 0, totalRead); }
private static void SendResponse(TcpClient client, string message) { //make sure the other end decodes with the same format! byte[] bytes = Encoding.Unicode.GetBytes(message); client.GetStream().Write(bytes, 0, bytes.Length); } } }
|
The only way to stop this server is with Ctrl+C (which is fairly standard for console servers).
Next, the client (see Listing 2). Its logic is similarly easy:
Listing 2. TCP Client
using System; using System.Text; using System.Net; using System.Net.Sockets;
namespace TcpClientTest { class Program { static void Main(string[] args) { TcpClient client = new TcpClient("127.0.0.1", 1330); bool done = false; Console.WriteLine("Type 'bye' to end connection"); while (!done) { Console.Write("Enter a message to send to server: "); string message = Console.ReadLine();
SendMessage(client, message);
string response = ReadResponse(client); Console.WriteLine("Response: " + response); done = response.Equals("BYE"); } }
private static void SendMessage(TcpClient client, string message) { //make sure the other end encodes with the same format! byte[] bytes = Encoding.Unicode.GetBytes(message); client.GetStream().Write(bytes, 0, bytes.Length); }
private static string ReadResponse(TcpClient client) { byte[] buffer = new byte[256]; int totalRead = 0; //read bytes until there are none left do { int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead); totalRead += read; } while (client.GetStream().DataAvailable); return Encoding.Unicode.GetString(buffer, 0, totalRead); } } }
|
|