Asynchronous Server Socket Example - c#

I found this code of Asynchronous Server Socket Example and i am trying to get the data out from the thread where i receive info to update a textbox, but i can't just use a simple string. I've tried something called Control.Invoke Method (Delegate, Object[]) to update it but when the program gets to the form1.Invoke(form1.updateTextBox, content); i get this error:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
The sad part is the MessageBox is working and displays the data I receive.
Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Stream_Socket_Listener {
public partial class Form1 : Form
{
public delegate void updateTextBoxDelegate(String textBoxString); // delegate
public updateTextBoxDelegate updateTextBox;
void updateTextBox1(string str)
{
textBox1.Text = str;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) { }
private void button1_Click(object sender, EventArgs e)
{
updateTextBox = new updateTextBoxDelegate(updateTextBox1);
AsynchronousSocketListener.StartListening();
}
}
// State object for reading client data asynchronously
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 AsynchronousSocketListener() { }
public static void StartListening()
{
// Data buffer for incoming data.
byte[] 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.Parse("127.0.0.1"),
11000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming
// connections.
try
{
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(new AsyncCallback(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.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{ String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject 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.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") -1)
{
// All the data has been read from the
// client. Display it on the console.
MessageBox.Show("Read " + content.Length + " bytes from socket. \n >Data" + content);
Form1 form1 = new Form1();
Application.DoEvents();
form1.Invoke(form1.updateTextBox, 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,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, 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.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
MessageBox.Show("Sent "+ bytesSent+ " bytes to client.");
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}

I think your problem is because you are invoking the form's method before the form is fully created. Try creating the form beforehand and ignore those calls until the form is ready. Additionally, you might need to do something like this:
if (InvokeRequired)
{
Invoke(new MethodInvoker(addMsg));
}
else
{
updateTextBox(content)
}
To avoid issues due to invoke a method from a different thread.

Related

Having issues sending an array of bytes using asynchronous socket in C#?

I 've following one of the .NET tutorials by Microsoft on how to implement an Asynchronous Server Socket. My goal is to implement a new function called writeToClient(byte[] input) inside Microsoft given code.
This function will be executed by another function located in a different application and upon being called, it will received an array of byte as an input and forward it to another application via socket running on a Raspberry Pi using Send() ideally.
The main issue I am facing so far is that Send(Socket handler, string data) function requires two arguments. To this end, I haven't been able to find a way I could combine these two applications into one and achieve my goal.
Any thoughts?
Thanks,
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
namespace UDCManager
{
public class StateObject
{
// 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();
// Client socket.
public Socket workSocket = null;
}
public class AsynchronousServerSocket
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static void StartListening()
{
IPAddress IP = IPAddress.Any;
IPEndPoint EP = new IPEndPoint(IP, 24000);
Socket listner = new Socket(IP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listner.Bind(EP);
listner.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...");
listner.BeginAccept(
new AsyncCallback(AcceptCallback),
listner);
// 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.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject 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.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -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,
new AsyncCallback(ReadCallback), state);
}
}
}
public static void Send(Socket handler, 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.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
**public static void writeToClient(byte[] input)
{
}**
public static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket 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());
}
}
}
}
If I understood the question correctly, you'd want something like this
// Expose a socket as a private variable, for example
private static Socket _socket;
public static void StartListening()
{
IPAddress IP = IPAddress.Any;
IPEndPoint EP = new IPEndPoint(IP, 24000);
_socket = new Socket(IP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // <<<< HERE
// ...
}
// then you could use it in the write method
public static void writeToClient(byte[] input)
{
// validate input for null, and size
// validate that _socket has been created (optionally)
_socket.BeginSend(input, 0, input.Length, 0,
new AsyncCallback(SendCallback), handler)
}
It may be simpler if you could start with synchronous code, and after that is working, convert it to new style async code using async/await

Socket issue in windows form. Socket stop replying when change tab control

i've made some program that starts an asynchronous socket that handles all client request.
Socket starts before Form1 is called, and works fine
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AsynchronousServer ascSv = new AsynchronousServer();
Application.Run(new Form1());
if (ascSv != null)
ascSv.Stop();
}
}
--Edited--- (Added AsynchronousServer.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Server
{
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 AsynchronousServer
{
public ManualResetEvent allDone = new ManualResetEvent(false);
Socket listener;
public Thread t;
public AsynchronousServer()
{
t = new Thread(StartListening);
t.Start();
}
public void Stop()
{
try
{
listener.Shutdown(SocketShutdown.Both);
listener.Disconnect(false);
try
{
listener.Close();
listener.Dispose();
}
catch { }
}
catch
{
}
if (t!=null &&t.IsAlive)
{
t.Abort();
t = null;
}
listener = null;
}
public void StartListening()
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("192.168.100.115"), 11000);
// Create a TCP/IP socket.
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
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(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch
{
//MessageBox.Show(e.Message);
}
}
public void AcceptCallback(IAsyncResult ar)
{
try
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch
{
}
}
public void ReadCallback(IAsyncResult ar)
{
try
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject 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.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -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.
//Choose what to do with the packet
string callBack= ClientController.GenerateResponseTo(content);
//Choose what server has to reply to client
Send(handler, #callBack+"*<EOF>");
//Send(handler, #"N:\tmp\2parts\save.cnf*1*<EOF>");
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
catch { }
}
private void Send(Socket handler, String data)
{
try
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
catch { }
}
private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket 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
{
}
}
}
}
Once i'm on GUI clients can connect to server to ask for they answer and server replies an sleep packet untill user inputs a valid path on GUI and clicks START.
Well that also works fine.
My issue is that when a client is succesfully conected it starts sending a callback to the server and server outputs its callback in a progressbar from a custom control i've made and that also "works" but the issue is:
If i keep the GUI on the server start tab. All works fine, clients get their answers and server adds and updates client's progress bar. BUT when i change the tab controll to the tab where the progress bar of all clients are displayed, server stops sending any replys to clients. Even if i go back to the server start tab it doesn't reply anymore.
I'm so hardstuck on this. Does anyone know where does my error come from?
I also upladed some pictures of a debug client and my issue:
Client connected to server and getting answers:
Changeing GUI tab and server stopping:
Problem solved. Thanks to Aram Kocharyan and Mong Zhu.
The error was that I was trying to access a GUI element from a different thread.
To modify a GUI element from another thread must use Invoke method of controll (Invoke calls the method from the thread that owns the component)
Example:
Form1.GetInstance.flowLayoutPanel_progress.Invoke(
new Action(() => Parse0(splited[1], out toReturn)));

Trying to Connect RPI to Unity via TCP

I am working on a small project and I am at the point where I want to connect my Raspberry Pi to Unity (running on my PC). I am able to make a connection running Visual Studio, but when I run the same code in Unity, no connections happen.
C# Code
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
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 AsynchronousSocketListener() {
}
public static void StartListening() {
// Data buffer for incoming data.
byte[] 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.GetHostEntry(Dns.GetHostName());
//IPAddress ipAddress = Array.Find(ipHostInfo.AddressList, x => x.AddressFamily == AddressFamily.InterNetwork);
IPAddress ipAddress = IPAddress.Any;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 6670);
Console.WriteLine($"Connected on {localEndPoint}");
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp );
// Bind the socket to the local endpoint and listen for incoming connections.
try {
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(
new AsyncCallback(AcceptCallback),
listener );
Console.WriteLine("Accepted");
// Wait until a connection is made before continuing.
allDone.WaitOne();
Console.WriteLine("After wait");
}
} 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.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject 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.
var stringRead = Encoding.ASCII.GetString(
state.buffer, 0, bytesRead);
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -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 {
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture);
Console.WriteLine(timestamp + ": " + stringRead);
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
//Test Code
Send(handler, "boogieboogie");
}
}
}
private static void Send(Socket handler, 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.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket 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) {
Thread t = new Thread(StartListening);
t.Start();
//FingerMovement.Service();
return 0;
}
}
The Python code is just doing a socket connect to the IP and port.
So to restate the question: Why does it not connect to the RPI when I run this in Unity? No connections occur, however, if I run the same exact code through VS, it connects just fine.
I allowed Unity in my firewall, tried running it in Admin, still nothing.
It's a bit of a long shot but have you enabled 'run in the background' checkbox in the player settings? I've had unity miss a whole lot of system events / transmissions while I was switching windows when this was off. I think all the child processes freeze when Unity looses focus by default, and I think that inclueds the async quasi-processes, or at the very least it surely includes your main thread which communicates with you

TCP Server & Client not receiving each other's information

I'm very new to all that TCP thing and I just can't find what's going wrong here. It might be pretty obvious for some of you. When I run the code, I run the Start process on the Server side, it displays 'waiting for connection', then I start the client, the later displays 'connected to ', I relaunch the start process on the server side and it displays 'Connected to the client' and then, on both sides, when I call the method SendThroughTCPSocket("whatever string"), I can see it being sent but nothing is being detected on the other side ?
What could I be doing wrong ?
How could I have both of them constantly listening to each other ?
SERVER SIDE :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server
{
// State object for reading client data asynchronously
public class StateObject
{
#region instance variables
// 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();
#endregion
}
public class AsynchronousSocketListener
{
public enum TransmissionSate
{
Waiting,
Receiving,
Received,
Sending,
Sent,
Off
}
#region class variables
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static IPHostEntry ipHostInfo;
public static IPAddress ipAddress;
public static IPEndPoint localEndPoint;
public static Socket listener;
public static Socket handler;
//flags
public static TransmissionSate currentState = TransmissionSate.Off;
#endregion
#region constructor
public AsynchronousSocketListener()
{
}
#endregion
#region Start Listening
//Start Listening for Client
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
ipHostInfo = Dns.Resolve(Dns.GetHostName());
ipAddress = ipHostInfo.AddressList[0];
localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
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(
new AsyncCallback(AcceptCallback),
listener);
//flag
currentState = TransmissionSate.Waiting;
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nConnected to the client.");
//Console.Read();
}
#endregion
#region Receive Methods
//Accept communication and Start reading
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
listener = (Socket)ar.AsyncState;
handler = listener.EndAccept(ar);
//flag
currentState = TransmissionSate.Receiving;
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
//Read and handle the information
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
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.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
//flag
currentState = TransmissionSate.Received;
// 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);
//reference
Data.lastResponse = content;
//react
Console.WriteLine("Server just received a request");
switch (content)
{
case "DataRequest":
Console.WriteLine("Client is trying to get the preset data");
SendThroughTCPSocket(Data.xmlToSend + Data.endOfFile);
break;
default:
Console.WriteLine("Unknown request from Client");
break;
}
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
#endregion
#region Send Methods
//Send data to a socket
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
//flag
currentState = TransmissionSate.Sending;
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
//Sending data and closing handler
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket 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);
//flag
currentState = TransmissionSate.Sent;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region SendThroughTCPSocket
public static void SendThroughTCPSocket(String data)
{
try
{
// Send data to the client
Send(handler, data);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region Stop Server
//Close Sever
public static void StopServer()
{
try
{
// Release the socket.
handler.Shutdown(SocketShutdown.Both);
handler.Close();
//flag
currentState = TransmissionSate.Off;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
}
}
CLIENT SIDE :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Client
{
// State object for receiving data from remote device.
public class StateObject
{
#region instance variables
// 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();
#endregion
}
public class AsynchronousClient
{
public enum TransmissionSate
{
Waiting,
Receiving,
Received,
Sending,
Sent,
Off
}
#region instance variables
// The port number for the remote device.
private const int port = 11000;
#endregion
#region class variables
// 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;
public static IPHostEntry ipHostInfo;
public static IPAddress ipAddress;
public static IPEndPoint remoteEP;
public static Socket client;
//flags
public static TransmissionSate currentState = TransmissionSate.Off;
public static bool isConnected = false;
#endregion
#region Start Client
//Start Client and use it
public static void StartClient()
{
// Connect to a remote device.
try
{
//flag
isConnected = false;
// Establish the remote endpoint for the socket.
// The name of the host
// remote device is the current device
ipHostInfo = Dns.Resolve(Dns.GetHostName());
ipAddress = ipHostInfo.AddressList[0];
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();
//flag
currentState = TransmissionSate.Waiting;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region Stop Client
//Close Client
public static void StopClient()
{
try
{
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
//flag
currentState = TransmissionSate.Off;
isConnected = false;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region Connect
//callback for connection
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();
//flag
isConnected = true;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region Receive
//Receive data
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
//flag
currentState = TransmissionSate.Receiving;
// 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());
}
}
//callback Receive
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();
//flag
currentState = TransmissionSate.Received;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region Send
//Send data
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
//flag
currentState = TransmissionSate.Sending;
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
//Callback send
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();
//flag
currentState = TransmissionSate.Sent;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
#region SendThroughTCPSocket
public static string SendThroughTCPSocket(String data)
{
try
{
// Send data to the remote device.
Send(client, data);
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);
return response;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return "<No response>";
}
}
#endregion
}
}
You need to implement a protocol on top of the socket. In your server you're using "" to determine that a message has ended and you only print it out once you get this. However, I can see nowhere in the client where you do this. Ideally you want to have a start of message token and an end of message token so that you can send multiple messages over a socket.
Change your client send method to
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data + "<EOF>");
//flag
currentState = TransmissionSate.Sending;
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
and this should work, but I do recommend implementing a protocol with start and end tokens.
In the receivecallback of the client you have code that never checks for any kind of protocol and simply attempts to keep on receiving data:
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);
}
At some stage your program must check the data to see if there is an end token of some sort.
Try changing this to the following:
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));
var endPos = state.sb.ToString().IndexOf("<EOF>");
if (endPos > -1) //we have a complete message. huzzah!
{
response = state.sb.ToString().Substring(0, endPos);
// Signal that all bytes have been received.
receiveDone.Set();
//flag
currentState = TransmissionSate.Received;
}
else
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
I must reiterate: you need to design a protocol if you are going to use raw sockets: a way to identify the start and end of discreet messages.

Close Client after the server respond

The only thing i want to change is to close the client connection after the client send message to the server and received respond from the server.
what i need to change in the client code ?
Server
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
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 AsynchronousSocketListener()
{
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] 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];
IPAddress ipAddress = System.Net.IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
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(
new AsyncCallback(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.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject 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.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -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,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, 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.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket 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:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
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 Program
{
public static ManualResetEvent connectDone = new ManualResetEvent(false);
public static ManualResetEvent sendDone = new ManualResetEvent(false);
public static ManualResetEvent receiveDone = new ManualResetEvent(false);
public static void Connect(EndPoint remoteEP, Socket client)
{
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
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 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, SocketFlags.None,
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());
}
}
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)
{
string response = state.sb.ToString();
Console.WriteLine(response);
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static void Main(string[] args)
{
IPAddress ipAddress = System.Net.IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
Socket sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
Connect(localEndPoint, sock);
string packet;
while (true)
{
packet = Console.ReadLine();
packet += "<EOF>";
Send(sock, packet);
Receive(sock);
connectDone.WaitOne();
}
}
}
The while loop in Main will run indefinitely.
while (true)
{
packet = Console.ReadLine();
packet += "<EOF>";
Send(sock, packet);
Receive(sock);
connectDone.WaitOne();
}
either remove it entirely (so that it runs only once) or add in a condition to exit the while loop.
as Diego pointed out the in the comments, you should close the socket after you are done, by
sock.Close();

Categories