I wrote a TCP Socket server and client a few months ago in my current project and they've been working flawlessly since then. But as of today I simply cannot get a connection between two machines that has been communicating without a hickup for a long time.
The setup is very straight forward: Two machines ('A' and 'B') are connected directly via an ethernet cable (no switch in between). Machine 'A' is also connected to my home network which allows for Internet access. Machine 'B' is only connected to 'A'. I am running the TCP server on 'B' and the client on 'A'.
I'm using the asynchronous .NET Socket features (BeginAccept etc on the server end and BeginConnect etc in the client end). Having debugged both ends I can only confirm that the server end never seems to get a call from the client. I haven't touched the code and it still works between other machines.
Also, there's no other comms problems between the two machines. I'm using Input Director to share one set of keyboard/mouse and normal UNC paths works fine to browse one machine from the other.
I have tested different ports and I've brought down the firewalls on both sides for good measure. I have released/renewed the connections on both sides, rebooted both machines and every other dummy option I can think of.
I confess I'm not terribly network savvy so I'd very much appreciate a few hints on what to look for next as I'm now out of ideas on what to check next. (I'm pretty sure it's gotta be something really stupid I've just overlooked. ;O)
EDIT (sample 'spike' code)
On request I adapted Microsoft's sample Socket code and compressed it a bit (below). I then tested running both server and client ends on machine 'B' which worked fine but on machine 'A' the same thing happened. The client got no contact with the server end. Here's the code:
public static class SocketServer
{
private class StateObject
{
public Socket _workSocket;
public const int BufferSize = 1024;
public readonly byte[] _buffer = new byte[BufferSize];
public readonly StringBuilder _sb = new StringBuilder();
}
private static readonly ManualResetEvent _s_allDone = new ManualResetEvent(false);
public static void StartListening()
{
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, 11000);
var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
_s_allDone.Reset();
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(acceptCallback, listener);
_s_allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
private static void acceptCallback(IAsyncResult ar)
{
_s_allDone.Set();
var listener = (Socket)ar.AsyncState;
var handler = listener.EndAccept(ar);
var state = new StateObject {_workSocket = handler};
handler.BeginReceive(state._buffer, 0, StateObject.BufferSize, 0, readCallback, state);
}
private static void readCallback(IAsyncResult ar)
{
var state = (StateObject)ar.AsyncState;
var handler = state._workSocket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead <= 0)
return;
state._sb.Append(Encoding.ASCII.GetString(state._buffer, 0, bytesRead));
var content = state._sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
}
else
{
handler.BeginReceive(state._buffer, 0, StateObject.BufferSize, 0, readCallback, state);
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
public static class SocketClient
{
private class StateObject
{
public Socket _workSocket;
public const int BufferSize = 256;
public readonly byte[] _receiveBuffer = new byte[BufferSize];
public readonly StringBuilder _sb = new StringBuilder();
}
private const int RemotePort = 11000;
private static readonly ManualResetEvent _s_connectDone = new ManualResetEvent(false);
private static readonly ManualResetEvent _s_sendDone = new ManualResetEvent(false);
private static readonly ManualResetEvent _s_receiveDone = new ManualResetEvent(false);
// The response from the remote device.
private static String _s_response = String.Empty;
private static void startClient()
{
try
{
_s_connectDone.WaitOne(2000); // <-- gives server time to boot when on same machine
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var remoteEndPoint = new IPEndPoint(ipAddress, RemotePort);
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEndPoint, connectCallback, client);
_s_connectDone.WaitOne();
send(client, "This is a test<EOF>");
_s_sendDone.WaitOne();
receive(client);
_s_receiveDone.WaitOne();
Console.WriteLine("Response received : {0}", _s_response);
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void connectCallback(IAsyncResult ar)
{
try
{
var client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint);
_s_connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void receive(Socket client)
{
try
{
var state = new StateObject {_workSocket = client};
client.BeginReceive(state._receiveBuffer, 0, StateObject.BufferSize, 0, receiveCallback, state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void receiveCallback(IAsyncResult ar)
{
try
{
var state = (StateObject)ar.AsyncState;
var client = state._workSocket;
var bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state._sb.Append(Encoding.ASCII.GetString(state._receiveBuffer, 0, bytesRead));
client.BeginReceive(state._receiveBuffer, 0, StateObject.BufferSize, 0, receiveCallback, state);
}
else
{
if (state._sb.Length > 1)
{
_s_response = state._sb.ToString();
}
_s_receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void send(Socket client, String data)
{
var byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0, sendCallback, client);
}
private static void sendCallback(IAsyncResult ar)
{
try
{
var client = (Socket)ar.AsyncState;
var bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
_s_sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main()
{
startClient();
return 0;
}
}
Related
Server :
public class TcpServer
{
private TcpListener tcpListener;
private static ManualResetEvent allDone = new ManualResetEvent(false);
public TcpServer(string url, int port)
{
tcpListener = new TcpListener(IPAddress.Parse(url), port);
pingMapper = new LightPingMapper();
}
public void Run()
{
tcpListener.Start();
Console.WriteLine("Server running");
while (true)
{
allDone.Reset();
tcpListener.BeginAcceptSocket(AcceptCallback, tcpListener);
Console.WriteLine("Accepting socket");
allDone.WaitOne();
}
Console.ReadLine();
}
private void AcceptCallback(IAsyncResult result)
{
try
{
allDone.Set();
var listener = (TcpListener) result.AsyncState;
var handler = listener.EndAcceptSocket(result);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
}
catch (Exception e)
{
Console.WriteLine($"Error accepting callback. {e.Message}");
}
}
private void ReadCallback(IAsyncResult asyncResult)
{
try
{
string content = string.Empty;
Console.WriteLine("Read data from socket");
StateObject state = (StateObject) asyncResult.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(asyncResult);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.buffer));
content = state.sb.ToString();
Console.WriteLine(content + " " + DateTime.Now);
}
}
catch (Exception e)
{
Console.WriteLine($"Error reading socket. {e.Message}");
}
}
}
class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
Client:
public class TCPClientWrapper
{
private TcpClient tcpClient;
private readonly string address;
private readonly int port;
public TCPClientWrapper(string address, int port)
{
InitTcpClient();
this.address = address;
this.port = port;
}
public void SendMessage()
{
for(int i=0; i < 10; i++)
{
if (!SocketConnected())
{
TryConnect();
}
byte[] buffer = Encoding.UTF8.GetBytes("Hello");
tcpClient.Client.Send(buffer);
Thread.Sleep(60000);
}
}
private void TryConnect()
{
bool isConnected = false;
while (true)
{
try
{
InitTcpClient();
tcpClient.Connect(IPAddress.Parse(address), port);
if (SocketConnected())
{
Console.WriteLine("TcpClient, Connected");
isConnected = true;
break;
}
}
catch (Exception e)
{
Console.WriteLine("TcpClient, connection failed. Try to reconnect after 30 seconds, {0}", e.Message);
}
finally
{
if (!isConnected)
{
tcpClient.Close();
Thread.Sleep(30000);
}
}
}
}
private void InitTcpClient()
{
tcpClient = new TcpClient();
tcpClient.SendTimeout = 15;
}
private bool SocketConnected()
{
var s = tcpClient.Client;
if (!s.Connected)
return false;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = s.Available == 0;
return !(part1 && part2);
}
}
The problem is that server read only first message , each next message is not received by server . The tcpClient is connected , but server doesn't receive any message . Could anyone suggest what is wrong with my code ?
In ReadCallback, you don't start the next read - so yes, your code only reads once.
Adding
handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
to the bottom of ReadCallback (when bytesRead > 0) should work. However! You aren't implementing proper framing, so you should be very cautious of that. A basic framing implementation for a text-based protocol (like this) would be to use some kind of line-end sentinel, and buffer data until you see a line-end, then process the line.
On TCP, you are only guaranteed to get the right bytes in the right order (or a failed socket eventually) - you are not guaranteed to get them in the same composition in terms of calls to Send exactly matching calls to Receive in terms of the numbers of bytes in each.
I need to exchange data from two machines with the highest throughput as possible. I have a server and a client.
The client needs to send several messages to the server (in the real application, 1 message every 22 ms). Instead of initializing the socket every time I need to send something, I would like to keep the connection open and to write several messages via socket that will be initialized once for all.
Here's my client in C#:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Diagnostics;
// State object for receiving data from remote device.
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int port = 11000;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String response = String.Empty;
private static Socket InitClient()
{
// Connect to a remote device.
// Establish the remote endpoint for the socket.
// The name of the
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[1];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return client;
}
private static void SendData(Socket client) {
try {
// Send test data to the remote device.
StringBuilder a = new StringBuilder();
Send(client, "This is a test<EOF>");
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReleaseClient(Socket client) {
try
{
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length >= 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
Socket client = InitClient();
for (int i = 0; i < 2; i++) {
SendData(client);
}
ReleaseClient(client);
Console.ReadLine();
return 0;
}
And this is the server in Python:
import socketserver
import socket
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(87380).strip()
print("{} wrote:".format(self.client_address[1]))
l = (str(len(self.data)))
print(l)
self.request.sendall(l.encode())
HOST, PORT = socket.gethostname(), 11000
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
server.serve_forever()
I can connect to the server, and if I'm calling this from C#:
InitClient();
SendData(client);
ReleaseClient(client);
Everything works fine. But if, like in my example, I'm trying to loop over SendData(), I can only send the first message and, when trying to send the second, the server gives me the following error:
System.Net.Sockets.SocketException (10053): An established connection was aborted by the software in your host machine
at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at AsynchronousClient.Receive(Socket client) in C:\Users\giuli\source\repos\ApplicationSending\ApplicationSending\Program.cs:line 133 (NdR the lines that corresponds to:
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);)
I cannot understand what is happening. Shouldn't it be possible to send multiple messages without having to re-initialize the socket?
This is how we establish the connection and keep sending multiple messages.
#Client.cs
private AutoResetEvent[] _autoSendReceiveEvents;
##Connection method
using (var connectArgs = new SocketAsyncEventArgs())
{
connectArgs.AcceptSocket = _socket;
connectArgs.RemoteEndPoint = _ipEndPoint;
connectArgs.Completed += OnCompleted;
var result = _socket.ConnectAsync(connectArgs);
if (result)
{
_autoConnectEvent.WaitOne();
}
var errorCode = connectArgs.SocketError;
if (errorCode != SocketError.Success)
{
CloseSocket();
throw new SocketException((int) errorCode);
}
}
##Sending Data
public void Send(string message)
{
if (!IsConnected)
{
throw new SocketException((int) SocketError.NotConnected);
}
var sendBuffer = GetBytes(message);
using (var sendReceiveArgs = new SocketAsyncEventArgs())
{
sendReceiveArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
sendReceiveArgs.AcceptSocket = _socket;
sendReceiveArgs.RemoteEndPoint = _ipEndPoint;
sendReceiveArgs.Completed += OnSend;
var result = _socket.SendAsync(sendReceiveArgs);
if (result)
{
_autoSendReceiveEvents[SendOperation].WaitOne();
}
}
}
##OnSend
private void OnSend(object sender, SocketAsyncEventArgs eventArgs)
{
try
{
if (eventArgs.SocketError != SocketError.Success)
{
CloseSocket();
_autoSendReceiveEvents[SendOperation].Set();
}
switch (eventArgs.LastOperation)
{
case SocketAsyncOperation.Send:
_autoSendReceiveEvents[SendOperation].Set();
break;
}
}
catch (Exception ex)
{
CloseSocket();
_autoSendReceiveEvents[SendOperation].Set();
}
}
I have attempted to create a TCP service that is able to achieve what I wish but sadly I am getting stuck at the last hurdle.
The Scenario:
A single server instance is running with 10 clients all connected, a client will send a command, and receive the response. This is all working fine. However the last scenario isn't working
When a client issues an "UPDATE" command, the server should then send a message back to all connected clients that they need to do something.
Example Comms:
1
Client A GetTime -----> Server
Client A <----- Time is... Server
2
Client A UPDATE ------> Server
Client A <------- Ack Server
Client A <------- DoUpdate Server
Client B <------- DoUpdate Server
Client C <------- DoUpdate Server
Comms 1 abover works, mainly because of the call to send and call to reeive, but for comms 2 I cannot workout how I can achieve this, at least not without opening a second port for the communication which isn't ideal.
Current attempt based on Microsoft Article
Server
class Program
{
public static int Main(String[] args)
{
AsynchronousSocketListener.StartListening();
return 0;
}
}
public class StateObject
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder Sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent AllDone = new ManualResetEvent(false);
public static void StartListening()
{
// Data buffer for incoming data.
//var bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
//??IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
//??IPAddress ipAddress = ipHostInfo.AddressList[0];
//??IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3030);
// Create a TCP/IP socket.
var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(new IPEndPoint(IPAddress.Any, 3030));
//listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
AllDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept((AcceptCallback), listener);
// Wait until a connection is made before continuing.
AllDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
AllDone.Set();
// Get the socket that handles the client request.
var listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
var state = new StateObject {WorkSocket = handler};
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
public static void ReadCallback(IAsyncResult ar)
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
var state = (StateObject)ar.AsyncState;
Socket handler = state.WorkSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.Sb.Append(Encoding.ASCII.GetString(
state.Buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
var content = state.Sb.ToString();
if (content.IndexOf("<EOF>", StringComparison.Ordinal) > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
var byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/*
public static int Main(String[] args)
{
StartListening();
return 0;
}
* */
}
Client Code
class Program
{
public static int Main(String[] args)
//static void Main(string[] args)
{
Console.Title = "Client ";
AsynchronousClient.StartClient();
Console.ReadLine();
return 0;
}
}
public class StateObject
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder Sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int Port = 3030;
// ManualResetEvent instances signal completion.
private static readonly ManualResetEvent ConnectDone =
new ManualResetEvent(false);
private static readonly ManualResetEvent SendDone =
new ManualResetEvent(false);
private static readonly ManualResetEvent ReceiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String _response = String.Empty;
public static void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
//??IPHostEntry ipHostInfo = Dns.Resolve("localhost");
//??IPAddress ipAddress = ipHostInfo.AddressList[0];
//??IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
//client.BeginConnect(remoteEP,
//new AsyncCallback(ConnectCallback), client);
var remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), Port);
client.BeginConnect(remoteEP, ConnectCallback, client);
ConnectDone.WaitOne();
// set receive to another thread so we can constantly receive, doesn't work as intended
//var thread = new Thread(() => ReadThread(client));
//thread.Start();
// Send test data to the remote device.
Send(client, "This is a test<EOF>");
SendDone.WaitOne();
//test remove
// Receive the response from the remote device.
Receive(client);
ReceiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", _response);
// Release the socket.
//client.Shutdown(SocketShutdown.Both);
//client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
// doesn't work as expected
private static void ReadThread(object ar)
{
var client = (Socket)ar;
while (true)
{
Receive(client);
ReceiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", _response);
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint);
// Signal that the connection has been made.
ConnectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
var state = new StateObject {WorkSocket = client};
// Begin receiving the data from the remote device.
client.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
var state = (StateObject)ar.AsyncState;
Socket client = state.WorkSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.Sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);
}
else
{
// All the data has arrived; put it in response.
if (state.Sb.Length > 1)
{
_response = state.Sb.ToString();
}
// Signal that all bytes have been received.
ReceiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
var byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
SendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/*
public static int Main(String[] args)
{
StartClient();
return 0;
}
*/
}
Previous system that worked
Server:
class Program
{
private static byte[] buffer = new byte[1024];
public static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public static List<Socket> clientSockets = new List<Socket>();
static void Main(string[] args)
{
Console.Title = "Server, " + clientSockets.Count + " clients are connected";
SetupServer();
Console.ReadLine();
}
public static void SetupServer()
{
Console.WriteLine("Setting up server...");
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 3030));
_serverSocket.Listen(10);
_serverSocket.BeginAccept(AcceptCallback, null);
Console.ReadLine();// stops cmd from closing
}
public static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _serverSocket.EndAccept(AR);
if (!clientSockets.Contains(socket))
clientSockets.Add(socket);
IPEndPoint remoteIPEndPoint = socket.RemoteEndPoint as IPEndPoint;
Console.WriteLine(remoteIPEndPoint.Address);
Console.WriteLine("Client Connected");
Console.Title = "Server, " + clientSockets.Count + " clients are connected";
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
_serverSocket.BeginAccept(AcceptCallback, null);
}
private static void RecieveCallBack(IAsyncResult AR)
{
var socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
var databuff = new byte[received];
Array.Copy(buffer, databuff, received);
string s = Encoding.ASCII.GetString(databuff);
Console.WriteLine("Text Received: " + s);
string response = string.Empty;
switch (s.ToLower())
{
case "get time":
response = DateTime.Now.ToLongTimeString();
break;
case "hello":
response = "olleh";
break;
case "update clients":
response = "";
SendData("Ack", socket);
doUpdateClients();
break;
default:
response = "Invavlid Request";
break;
}
SendData(response, socket);
}
private static void SendData(string Data, Socket socket)
{
byte[] data = Encoding.ASCII.GetBytes(Data);
socket.BeginSend(data, 0, data.Length, SocketFlags.None, sendCallback, socket);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
}
private static void doUpdateClients()
{
// need to send an update message to all the clients
var upd = new Thread((UpdateClients));
upd.Start();
}
private static void UpdateClients()
{
Thread.Sleep(5000);
foreach (var sock in clientSockets)
{
SendData("UpdateClients", sock);
}
}
private static void sendCallback(IAsyncResult AR)
{
var socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
//
}
}
Client:
class Program
{
private static byte[] buffer = new byte[1024];
public static Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
Console.Title = "Client ";
LoopConnect();
//ReceiveLoopStart();
//_clientSocket.Listen(10);
SendLoop();
Console.ReadLine();
}
private static void LoopConnect()
{
while (!_clientSocket.Connected)
{
try
{
_clientSocket.Connect(IPAddress.Parse("127.0.0.1"), 3030);
}
catch (SocketException se)
{
}
}
Console.WriteLine("Connected");
}
private static void ReceiveLoopStart()
{
//_clientSocket.Bind(new IPEndPoint(IPAddress.Any, 3030));
//_clientSocket.Listen(10);
_clientSocket.BeginAccept(AcceptCallback, null);
Thread receiveThread = new Thread(ReceiveLoop);
receiveThread.Start();
}
private static void ReceiveLoop()
{
_clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, _clientSocket);
_clientSocket.BeginAccept(AcceptCallback, null);
}
private static void RecieveCallBack(IAsyncResult AR)
{
int received = _clientSocket.EndReceive(AR);
var databuff = new byte[received];
Array.Copy(buffer, databuff, received);
string s = Encoding.ASCII.GetString(databuff);
Console.WriteLine("Text Received: " + s);
string response = string.Empty;
switch (s.ToLower())
{
case "get time":
response = DateTime.Now.ToLongTimeString();
break;
case "hello":
response = "olleh";
break;
default:
response = "Invavlid Request";
break;
}
}
public static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _clientSocket.EndAccept(AR);
Console.WriteLine("Client Connected");
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
_clientSocket.BeginAccept(AcceptCallback, null);
}
private static void SendLoop()
{
while (true)
{
Console.Write("Enter Request: ");
string req = Console.ReadLine();
var buffer = Encoding.ASCII.GetBytes(req);
_clientSocket.Send(buffer);
var tempBuff = new byte[1024];
int rec = _clientSocket.Receive(tempBuff);
var data = new byte[rec];
Array.Copy(tempBuff, data, rec);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
}
}
}
}
I don't have an example up my sleeve here in C# but what you need to learn is to use the select api.
You only need a single thread to do this. You use the same thread to process all sockets that are in use at any point in time.
If nobody is connected you only have the listening socket. And you then only use the select api to watch what happens on that socket. Select is a blocking call when no timeout is specified. If data is available, then that means that you can call accept. The result of accept is as you know another socket. You now use 2 sockets in select. Again select will block until one of those sockets has data. Perhaps the listening socket again, so you get another socket after calling accept. You now use 3 sockets in select. Suppose now one of the accept sockets have data available you will see that by the using the select api properly. And you can then use any of those sockets to send something over it, except of course the listening socket that is not intended for sending.
More info can be found here :
http://www.codeproject.com/Articles/20066/A-scalable-client-server-using-select-socket-funct
It uses what I explained and gives more elaborate explanations too.
I'm not getting in to your design , but it seems like you can't even reference the other clients.
why don't you save a collection of sockets like so :
private List<Socket> _handlers = new List<Socket>();
public static void AcceptCallback(IAsyncResult ar)
{
Socket handler = listener.EndAccept(ar);
var state = new StateObject {WorkSocket = handler};
handlers.Add(handler);
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
And then on receive according to the message type or whatever you should notify these clients.( all of them not just the one currently passed to the ReciveCallback.
public static void ReadCallback(IAsyncResult ar)
{
if("<EOF>")
{
foreach(var h in _handlers)
{
Send(h,data);
}
}
}
I'm trying to develop a console application behaving as an asynchronous socket client in C#. You can see the code below:
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
class Program
{
private static readonly string hostIp = ConfigurationManager.AppSettings["HostIp"];
private static readonly int port = Int32.Parse(ConfigurationManager.AppSettings["HostPort"]);
private static Socket client;
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static Thread receiveThread;
static int Main(string[] args)
{
EventLog appLog = new EventLog();
appLog.Source = "xApp";
try
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(hostIp);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client, "Login Message");
sendDone.WaitOne();
receiveThread = new Thread((ThreadStart)delegate
{
while (true)
{
Receive(client);
receiveDone.WaitOne();
Thread.Sleep(1);
}
});
receiveThread.Start();
}
catch (Exception ex)
{
appLog.WriteEntry(
"An exception occured: " +
" ex: " + ex.ToString() +
" stack trace: " + ex.StackTrace,
System.Diagnostics.EventLogEntryType.Error);
}
return 0;
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
Console.WriteLine("Response received : {0}", state.sb.ToString());
string[] args = state.sb.ToString().Split(';');
switch (args[1])
{
case "CREATEBOOK":
ProcessInput(args);
break;
case "CONFIRMBOOK":
if (args[2] == "true")
{
ConfirmProcess();
}
break;
default:
break;
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
byte[] byteData = Encoding.Unicode.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
When I'm debugging I see that the code does the work as expected but the memory size used by process is increasing every moment. I think that the reason of the memory leak is the following code piece:
receiveThread = new Thread((ThreadStart)delegate
{
while (true)
{
Receive(client);
receiveDone.WaitOne();
Thread.Sleep(1);
}
});
receiveThread.Start();
But I don't have any idea about the change I have to do. Do you have any tip?
Thanks in advance,
I think the problem is in your Receive method which you are calling in a while loop. Basically you are creating a new StateObject every time you loop around.
// Create the state object.
StateObject state = new StateObject();
Try and store the state object as a class variable and reuse it. Maybe add a Reset method if you need to re-initialilze it again. This article shows a way to build a very efficient asynchronous socket which you may find useful.
Basically I made two C# applications, a client and a server. The client connects to the server (via sockets), then sends a packet containing some text, and the server should reply.
My problem is: the server sends (or the client receives) the response packet only when it closes (ALT+F4). I'd like some help. I'll copypaste below the source code for both the projects.
Client:
public class StateObject
{
public Socket skt = null;
public const int BufferSize = 256;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient
{
private const int port = 11000;
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
private static String response = String.Empty;
public static string command;
public static Socket client;
public static void StartClient()
{
try
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("127.0.0.1"));
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
while (true)
{
command = Console.ReadLine();
if (command == "exit")
{
Console.WriteLine("Terminating...");
client.Shutdown(SocketShutdown.Both);
client.Close();
Environment.Exit(0);
}
else
{
Send(client, command + "<EOF>");
sendDone.WaitOne();
Receive(client);
receiveDone.WaitOne();
Console.WriteLine("Response received : {0}", ProcessResponse(response));
client.Shutdown(SocketShutdown.Both);
client.Close();
}
//Console.CancelKeyPress += (sender, e) =>
//{
// Console.WriteLine("Terminating...");
// client.Shutdown(SocketShutdown.Both);
// client.Close();
// Environment.Exit(0);
//};
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static public string ProcessResponse(string pkt)
{
string response = null;
response = pkt.Replace("<EOF>","");
return response;
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
StateObject state = new StateObject();
state.skt = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.skt;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
return 0;
}
Server:
public class Program
{
public class StateObject
{
public Socket skt = null;
public const int buffersize = 1024;
public byte[] buffer = new byte[buffersize];
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener() { }
public static Socket handler;
public static void StartListening()
{
byte[] bytes = new Byte[1024];
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
allDone.Reset();
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.skt = handler;
handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.skt;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, ProcessResponse(content));
Send(handler, content);
}
else
{
handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static public string ProcessResponse(String pkt)
{
string response = null;
response = pkt.Replace("<EOF>", "");
return response;
}
}
public static void Main(string[] args)
{
AsynchronousSocketListener.StartListening();
}
}
In your Client receive callback:
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.skt;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
You won't ever drop down into the else block unless the socket is explicitly closed (or there is some kind of other error in the connection). Therefore receiveDone never gets set and your main loop is simply stuck waiting for a "response".
If you want to process a "complete message" when it comes in, then check for your <EOF> value after you append the current string to your buffer like this:
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// it's not a "response" unless it's terminated with "<EOF>" right?
response = state.sb.ToString();
if (response.IndexOf("<EOF>") != -1)
{
state.sb.Clear();
receiveDone.Set();
}
else
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString(); // this is a partial response, not terminated with "<EOF>"
}
receiveDone.Set();
}
Note that response mechanism being used is extremely limited as it would fail for multiple messages coming in at the same time like: Hello<EOF> World!<EOF> It would treat those two messages as one long message. (I realize your example is only sending one "message".)
You're almost certainly going to have to deal with that scenario in any real world application that sends "control" messages in addition to "content" messages. To handle that you'd look for <EOF> using IndexOf() and extract the text up to that point and process that "complete message". Afterwards you'd keep looping as long as <EOF> is still found to process the other pending messages. You'd also have to REMOVE those processed complete messages from the StringBuilder in such a way that any remaining values after the <EOF> are left in place so that when partial messages come in the new data can be appended to the existing data. This is because your data can also be split up when it is sent, resulting in multiple "chunks" of data being received even though it is logically one "complete message" when you sent it. So one send with Complete Message<EOF> could result in one or more receives such as Comp followed by lete Message<EOF>. Your code has to be able to deal with these realities of TCP communication...