I've created a basic C# application that is receiving and sending data with sockets. Currently I'm able to send data from my client to my server and I can receive response.
My problem is: As a client I don't know how to check if the server has send me anything new. Normally I send something as client and receive response there is no problem but sometimes server has to send me some information.
This is my current code sample, I'll update this post if I change the code
My server side code is like this:
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 static ManualResetEvent allDone = new ManualResetEvent(false);
public void StartListening()
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 10101);
Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
ClientList.Add(handler);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
public void ReadCallback(IAsyncResult ar)
{
string content = string.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf("_|_!#*#_") > -1)
{
HandleIncomingMessage(handler, content.Substring(0, content.Length - 8));
}
else
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
}
}
private void HandleIncomingMessage(Socket handler, string data)
{
CheckForIllegalCrossThreadCalls = false;
Response response = new Response();
byte[] byteData = Encoding.UTF8.GetBytes(data);
listView1.Items.Add(data);
response = ParserToSocket(data);
if (response == null)
{
response = new Response();
response.Status = "false";
response.Message = "Json not valid" + data;
}
if (response.Status == null)
response.Status = "false";
if (response.Message == null)
response.Message = "Error while creating response message";
byte[] ByteArrayToSend = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(response) + "_|_!#*#_");
handler.BeginSend(ByteArrayToSend, 0, ByteArrayToSend.Length, 0, new AsyncCallback(SendCallback), handler);
}
private void SendCallback(IAsyncResult ar)
{
try
{
StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
StateObject state = (StateObject)ar.AsyncState;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
and this is code for my client side :
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 512;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
private string response = string.Empty;
public Socket ConnectedSocket;
IPHostEntry ipHostInfo;
IPAddress ipAddress;
IPEndPoint remoteEP;
private string StartClient()
{
try
{
ipHostInfo = Dns.GetHostEntry("127.0.0.1");
ipAddress = ipHostInfo.AddressList[0];
remoteEP = new IPEndPoint(ipAddress, 10101);
ConnectedSocket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
ConnectedSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), ConnectedSocket);
return "";
}
catch (Exception e)
{
Console.WriteLine("CLIENT ERROR : \n" + e.ToString());
return "";
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.WriteLine("Client connected to server.");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public string SendMessageToServer(string text)
{
StartClient();
response = string.Empty;
text += "_|_!#*#_";
byte[] byteData = Encoding.UTF8.GetBytes(text);
ConnectedSocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), ConnectedSocket);
while(response.IndexOf("_|_!#*#_") == -1)
{
}
response = response.Replace("_|_!#*#_", "");
return response;
}
private void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
StateObject state = new StateObject();
state.workSocket = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead));
response = state.sb.ToString();
if (response.IndexOf("_|_!#*#_") != -1)
{
state.sb.Clear();
return;
}
else
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
client.EndReceive(ar);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Related
I have a server in C that send message to unity. In Unity, I can receive data once, but when the server sends a new message, unity receives nothing.
For example: Unity can connect to server, receive the first message that said "move right" and move the camera of Unity to the right but then if the server send "move left" or anything else unity is block in the function receive which calls BeginReceive:
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
Code of my server:
void connectToUnity() {
SOCKADDR_IN sin;
WSAStartup(MAKEWORD(2, 0), &WSAData);
sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons(53660);
bind(sock, (SOCKADDR*)&sin, sizeof(sin));
listen(sock, 0);
printf("Connexion to unity\n");
}
void sendDataToUnity(const char * mouvement) {
SOCKET csock;
while (1)
{
int sinsize = sizeof(csin);
if ((csock = accept(sock, (SOCKADDR*)&csin, &sinsize)) != INVALID_SOCKET)
{
send(csock, mouvement, 14, 0);
printf("Donnees envoyees \n");
return;
}
else {
printf("Rien n'a ete envoye");
}
}
}
Code in Unity:
public bool ConnectToServer(string hostAdd, int port)
{
//connect the socket to the server
try
{
//create end point to connect
conn = new IPEndPoint(IPAddress.Parse(hostAdd), port);
//connect to server
clientSocket.BeginConnect(conn, new AsyncCallback(ConnectCallback), clientSocket);
socketReady = true;
connectDone.WaitOne();
Debug.Log("Client socket ready: " + socketReady);
// Receive the response from the remote device.
Receive(clientSocket);
//receiveDone.WaitOne();
}
catch (Exception ex)
{
Debug.Log("socket error: " + ex.Message);
}
return socketReady;
}
//async call to connect
static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket
Socket client = (Socket)ar.AsyncState;
// Complete the connection
client.EndConnect(ar);
Debug.Log("Client Socket connected to: " + client.RemoteEndPoint);
connectDone.Set();
}
catch (Exception e)
{
Debug.Log("Error connecting: " + e);
}
}
private static void Receive(Socket client)
{
try
{
Debug.Log("Try to receive");
// 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)
{
Debug.Log(e);
}
}
static void ReceiveCallback(IAsyncResult ar)
{
try
{
//Read data from the remote device.
Debug.Log("receive callback");
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
Debug.Log("Il y a une réponse");
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
response = state.sb.ToString();
Debug.Log(response);
//client.Shutdown(SocketShutdown.Both);
}
else
{
if(state.sb.Length > 1)
{
response = state.sb.ToString();
Debug.Log(response);
}
}
}
catch (Exception ex)
{
Debug.Log("Error: " + ex.Message);
}
}
The function receive is called once in the function ConnectToServer, then I tried to call again in the update like this:
void Update()
{
if (response.Contains("right"))
{
Debug.Log("Move to the right ");
float x = Camera.main.transform.localEulerAngles.x;
float y = Camera.main.transform.localEulerAngles.y;
DeplacementCamera.moveRight(x, y);
response = "";
Receive(clientSocket);
}
}
I have already see this post but without success or maybe I tried it in the wrong way:
Why does BeginReceive() not return for more than one read?
Edit: In the function ReceiveCallback the else is never reached.
you may change your method
private void SetupReceiveCallback(Socket sock)
{
try
{
DataBuffer = new byte[BufferSize];
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
sock.BeginReceive(DataBuffer, 0, DataBuffer.Length, SocketFlags.None, recieveData, _socket);
}
catch (Exception E)
{
}
}
private void OnRecievedData(IAsyncResult ar)
{
Socket sock = (Socket)ar.AsyncState;
try
{
if (sock.Connected)
{
int nBytesRec = sock.EndReceive(ar);
if (nBytesRec > 0)
{
string Data = Encoding.UTF8.GetString(DataBuffer);
if (Data.Length != 4)
{
string JsonString = Data;
if (!string.IsNullOrEmpty(JsonString))
{
try
{
//Add you code processing here
}
catch (Exception ex)
{
}
}
BufferSize = 4;
}
else
{
BufferSize = BitConverter.ToInt32(DataBuffer, 0);
}
}
SetupReceiveCallback(sock);
}
else
// on not connected to socket
}
catch (Exception E)
{
}
}
public bool Connect(string IP, int Port)
{
try
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//if (IsValidIP(IP))
//{
// IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(IP), Port);
// _socket.Connect(epServer);
//}
//else
//{
// _socket.Connect(IP, Port);
//}
//SetupReceiveCallback(_socket);
}
catch(Exception ex)
{
}
return false;
}
I have a WPF 'server' app using a socket, with a UWP 'client' app using StreamSocket. I can transfer small amounts of data fine, but if I try and send a 288kb file, the file is received fine by the WPF app but the UWP app never receives the response.
WPF code:
In the ReadCallback method, the content is sent in the format of command;printername{data}. The data is all received fine but the Send method called before processing the data is not received.
public void Start()
{
Task.Run(() =>
{
var ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList.FirstOrDefault(x =>x.AddressFamily == AddressFamily.InterNetwork);
var localEndPoint = new IPEndPoint(ipAddress, Settings.Default.PrintPort);
listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
IsRunning = true;
while (true)
{
// Set the event to nonsignaled state.
AllDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
AcceptCallback,
listener);
// Wait until a connection is made before continuing.
AllDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
});
}
public void AcceptCallback(IAsyncResult ar)
{
if(!IsRunning) return;
// Signal the main thread to continue.
AllDone.Set();
// Get the socket that handles the client request.
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject {WorkSocket = handler};
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
ReadCallback, state);
}
public static void ReadCallback(IAsyncResult ar)
{
try
{
// 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.
var content = state.Sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
content = content.Remove(content.IndexOf("<EOF>"));
if (content.StartsWith("PrintFile"))
{
if (!content.Contains("{"))
{
Send(handler, "false");
return;
}
var parts = content.Substring(0, content.IndexOf('{')).Split(';');
if (string.IsNullOrEmpty(parts[1]))
{
Send(handler, "false");
return;
}
// This send never gets received
Send(handler, "true");
//But the file is printed
var base64 = content.Substring(content.IndexOf('{') + 1);
base64 = base64.Remove(base64.LastIndexOf('}'));
var doc = new Spire.Pdf.PdfDocument(Convert.FromBase64String(base64));
doc.PrintSettings.PrinterName = parts[1];
doc.Print();
}
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
ReadCallback, state);
}
}
}
catch
{
//Ignore
}
}
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,
SendCallback, handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
UWP Code:
public bool PrintFlle(string printer, string base64)
{
try
{
var result = Send($"PrintFile;{printer}{{{base64}}}<EOF>").Result;
return bool.TryParse(result, out var b) && b;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
socket.Dispose();
}
}
private async Task<string> Send(string input)
{
try
{
socket = new StreamSocket();
await socket.ConnectAsync(HostName, App.LocalSettings.Values["PrintPort"] as string);
using (Stream outputStream = socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(input);
await streamWriter.FlushAsync();
}
}
using (Stream inputStream = socket.InputStream.AsStreamForRead())
{
using (StreamReader streamReader = new StreamReader(inputStream))
{
var output = await streamReader.ReadLineAsync();
socket.Dispose();
return output;
}
}
}
catch (Exception e)
{
socket.Dispose();
return "";
}
}
I'm trying to build an Asynchronous Chat Server and this is what I got so far:
Server
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class StateObject
{
public Socket workSocket = 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 void StartListening()
{
byte[] bytes = new Byte[1024];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 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.workSocket = 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.workSocket;
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, 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
{
Socket handler = (Socket)ar.AsyncState;
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.Threading;
using System.Text;
public class StateObject
{
public Socket workSocket = 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;
static String username = "";
static int a = 1;
private static void StartClient()
{
try
{
Console.WriteLine("Username: ");
username = Console.ReadLine();
while (a == 1)
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
Console.WriteLine("Receiver: ");
String receiver = Console.ReadLine();
Console.WriteLine("Message: ");
String message = Console.ReadLine();
String Message = username + "[" + receiver + "[" + message + "<EOF>";
Send(client, Message);
sendDone.WaitOne();
Receive(client);
receiveDone.WaitOne();
Console.WriteLine("Response received : {0}", response);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
StateObject state = new StateObject();
state.workSocket = 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.workSocket;
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;
}
}
I'm able to send messages to the server and get back an answer, but the connection is cut every time and I have to reconnect it and like this I wouldn't be able to get messages after I send one. I'm looking for a way to connect my client to the server, send messages in both ways and stop the connection manualy.
Furthermore I'm looking for a way to send messages from one client to another one and to send a message to all clients, who are connected to the server.
Another Question I have, how can I set up multiple ports and let the server listen to all ports? I wanted to open one port for the login and one port for the messages.
I'm looking for a way to connect my client to the server, send messages in both ways and stop the connection manualy.
Closing the connection could be done by adding a disconnect call after the loop: client.Disconnect(false). After some exit condition you simply quit the loop.
It would be preferable to create the client in a using statement though, this way it will be disposed automatically.
but the connection is cut every time
because your explicitly close it in SendCallback
Socket handler = (Socket) ar.AsyncState;
handler.Shutdown(SocketShutdown.Both);
handler.Close();
You may call handler.BeginReceive instead
I am trying to create asynchronous socket client in multithreaded environment but it is not working correctly.
As below sample code,
If i create new AsyncSocketClient and call StartClent from multi-threaded environment it will process only one or two for rest, it is not processing.(I am creating new AsyncSocketClient with every new request)
Is it because of static variables,
class AsyncSocketClient
{
private static AutoResetEvent sendDone =
new AutoResetEvent(false);
private static AutoResetEvent receiveDone =
new AutoResetEvent(false);
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
static private String response = "";
public void StartClent()
{
Socket workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// clientSock.ReceiveTimeout = 1;
try
{
workSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, 8080), new AsyncCallback(ConnectCallBack), workSocket);
connectDone.WaitOne();
Send(s.workSocket, "<EOF>");
sendDone.WaitOne();
Receive(workSocket);
receiveDone.WaitOne();
}
catch(Exception ex)
{
}
}
private void ConnectCallBack(IAsyncResult ar)
{
Socket workSocket = (Socket)ar.AsyncState;
workSocket.EndConnect(ar);
connectDone.Set();
}
private void Receive(Socket client)
{
StateObject state = new StateObject();
state.workSocket = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int byteReceived= client.EndReceive(ar);
if (byteReceived > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, state.buffer.Length));
Array.Clear(state.buffer, 0, state.buffer.Length);
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
private void Send(Socket client,string data)
{
byte[] sendBufer = Encoding.ASCII.GetBytes(data);
client.BeginSend(sendBufer, 0, sendBufer.Length, 0, new AsyncCallback(BeginSendCallBack), client);
}
private void BeginSendCallBack(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int byteSent= client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", byteSent);
sendDone.Set();
}
}
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 30;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
Here is an example of a non blocking client and server with a simple echo implemented. There is no error checking and nothing is closed correctly which should be done. The server has some synchronous code just to make it easier to follow.
Client
public class AsyncClient
{
private const int Port = 9999;
private readonly string _clientId;
private readonly Random _random;
public AsyncClient(int clientId)
{
_clientId = string.Format("Client Id: {0}", clientId);
_random = new Random(clientId);
}
public void StartClient()
{
try
{
var workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var state = new ClientState { WorkSocket = workSocket };
workSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, Port), ConnectCallBack, state);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void ConnectCallBack(IAsyncResult ar)
{
var state = (ClientState) ar.AsyncState;
state.WorkSocket.EndConnect(ar);
Send(state);
}
private void Receive(ClientState clientState)
{
clientState.WorkSocket.BeginReceive(clientState.Buffer, 0, ClientState.BufferSize, 0, ReceiveCallBack, clientState);
}
private void ReceiveCallBack(IAsyncResult ar)
{
var state = (ClientState) ar.AsyncState;
Socket client = state.WorkSocket;
int byteReceived= client.EndReceive(ar);
if (byteReceived > 0)
{
var receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
Console.WriteLine("From Server: " + receivedString);
Array.Clear(state.Buffer, 0, state.Buffer.Length);
state.Count++;
Thread.Sleep(1000 + _random.Next(2000));
Send(state);
}
}
private void Send(ClientState clientState)
{
Console.WriteLine("Sending " + _clientId);
byte[] buffer = Encoding.UTF8.GetBytes(string.Format("Send from Thread {0} Client id {1} Count {2}", Thread.CurrentThread.ManagedThreadId, _clientId,clientState.Count));
clientState.WorkSocket.BeginSend(buffer, 0, buffer.Length, 0, BeginSendCallBack, clientState);
}
private void BeginSendCallBack(IAsyncResult ar)
{
var state = (ClientState) ar.AsyncState;
int byteSent= state.WorkSocket.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", byteSent);
Receive(state);
}
}
public class ClientState
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
public int Count = 0;
}
Server
public class AsyncServer
{
private const int Port = 9999;
public void StartServer()
{
var thread = new Thread(Run) {IsBackground = true};
thread.Start();
}
private void Run()
{
Console.WriteLine("Running");
var tcpListener = new TcpListener(IPAddress.Loopback, Port);
tcpListener.Start();
while (true)
{
Console.WriteLine("Before Accept");
var state = new ServerState {WorkSocket = tcpListener.AcceptSocket()};
Console.WriteLine("Before Recieve");
Receive(state);
}
}
private void Receive(ServerState state)
{
state.WorkSocket.BeginReceive(state.Buffer, 0, ServerState.BufferSize, 0, ReceiveCallBack, state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
Console.WriteLine("ReceiveCallBack");
var state = (ServerState) ar.AsyncState;
try
{
int byteReceived= state.WorkSocket.EndReceive(ar);
if (byteReceived > 0)
{
var receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
Console.WriteLine("Received: " + receivedString);
var bytesToSend = Encoding.UTF8.GetBytes("Server Got --> " + receivedString);
Array.Copy(bytesToSend, state.Buffer, bytesToSend.Length);
state.WorkSocket.Send(state.Buffer, 0, bytesToSend.Length, SocketFlags.None);
Array.Clear(state.Buffer, 0, state.Buffer.Length);
Receive(state);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private class ServerState
{
public const int BufferSize = 1024;
public readonly byte[] Buffer = new byte[1024];
public Socket WorkSocket;
}
I have run this using a console you can either have two applications or just launch the client and server separately.
static void Main(string[] args)
{
if (args.Length != 0)
{
var server = new AsyncServer();
server.StartServer();
}
else
{
for(int i = 0; i < 10; i++)
{
var client = new AsyncClient(i);
client.StartClient();
}
}
Console.WriteLine("Press a key to exit");
Console.ReadKey();
}
I am having a server and multiple clients in my project. Server need to send the files by request, and it store the files from clients. I have coding, that connects with multiple clients but receives one file at time. Other file store requests will proceed after the previous file received completely.
My files size is around 200 MB. So it takes more time to respond all clients. How i will solve this. Any one help me. Thanks in advance.
public partial class Form1 : Form
{
byte[] Echo;
byte[] a;
Thread t1;
int flag = 0;
string receivedPath = "yok";
public delegate void MyDelegate();
private string fileName;
public Form1()
{
t1 = new Thread(new ThreadStart(StartListening));
t1.Start();
InitializeComponent();
}
delegate void SetTextCallback(string text);
public class StateObject
{
// Client socket.
public Socket workSocket = null;
public const int BufferSize = 8069;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
}
public static ManualResetEvent allDone = new ManualResetEvent(true);
public void StartListening()
{
StateObject state = new StateObject();
byte[] bytes = new Byte[8069];
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 9050);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(ipEnd);
listener.Listen(100);
while (true)
{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}
}
catch (Exception ex)
{
SetText(ex.ToString());
}
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state);
flag = 0;
}
public void ReadCallback(IAsyncResult ar)
{
int fileNameLen = 1;
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
try
{
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
if (flag == 0)
{
fileNameLen = BitConverter.ToInt32(state.buffer, 0);
fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen);
receivedPath = #"D:\" + fileName;
flag++;
}
if (flag >= 1)
{
BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append));
if (flag == 1)
{
writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen));
flag++;
}
else
writer.Write(state.buffer, 0, bytesRead);
writer.Close();
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state);
}
}
else
{
allDone.Set();
Invoke(new MyDelegate(LabelWriter));
}
}
catch
{
}
}
public void LabelWriter()
{
label1.Text = "Data has been received " + fileName;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
t1.Abort();
}
}
You can trigger your allDone event within the AcceptCallback method. Immidiatly after accepting a client, you can spin of a process that is communicating with that client while in the meantime start listening for the next client.