I'm working on a web server in C# and I have it running on Asynchronous socket calls. The weird thing is that for some reason, when you start loading pages, the 3rd request is where the browser won't connect. It just keeps saying "Connecting..." and doesn't ever stop. If I hit stop. and then refresh, it will load again, but if I try another time after that it does the thing where it doesn't load again. And it continues in that cycle. I'm not really sure what is making it do that.
The code is kind of hacked together from a couple of examples and some old code I had. Any miscellaneous tips would be helpful as well.
Heres my little Listener class that handles everything
(pastied here. thought it might be easier to read this way)
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using irek.Request;
using irek.Configuration;
namespace irek.Server
{
public class Listener
{
private int port;
private Socket server;
private Byte[] data = new Byte[2048];
static ManualResetEvent allDone = new ManualResetEvent(false);
public Config config;
public Listener(Config cfg)
{
port = int.Parse(cfg.Get("port"));
config = cfg;
ServicePointManager.DefaultConnectionLimit = 20;
}
public void Run()
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, port);
server.Bind(iep);
Console.WriteLine("Server Initialized.");
server.Listen(5);
Console.WriteLine("Listening...");
while (true)
{
allDone.Reset();
server.BeginAccept(new AsyncCallback(AcceptCon), server);
allDone.WaitOne();
}
}
private void AcceptCon(IAsyncResult iar)
{
allDone.Set();
Socket s = (Socket)iar.AsyncState;
Socket s2 = s.EndAccept(iar);
SocketStateObject state = new SocketStateObject();
state.workSocket = s2;
s2.BeginReceive(state.buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(Read), state);
}
private void Read(IAsyncResult iar)
{
try
{
SocketStateObject state = (SocketStateObject)iar.AsyncState;
Socket s = state.workSocket;
int read = s.EndReceive(iar);
if (read > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
SocketStateObject nextState = new SocketStateObject();
nextState.workSocket = s;
s.BeginReceive(state.buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(Read), nextState);
}
if (state.sb.Length > 1)
{
string requestString = state.sb.ToString();
// HANDLE REQUEST HERE
byte[] answer = RequestHandler.Handle(requestString, ref config);
// Temporary response
/*
string resp = "<h1>It Works!</h1>";
string head = "HTTP/1.1 200 OK\r\nContent-Type: text/html;\r\nServer: irek\r\nContent-Length:"+resp.Length+"\r\n\r\n";
byte[] answer = Encoding.ASCII.GetBytes(head+resp);
// end temp.
*/
state.workSocket.BeginSend(answer, 0, answer.Length, SocketFlags.None, new AsyncCallback(Send), s);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return;
}
}
private void Send(IAsyncResult iar)
{
try
{
SocketStateObject state = (SocketStateObject)iar.AsyncState;
int sent = state.workSocket.EndSend(iar);
state.workSocket.Shutdown(SocketShutdown.Both);
state.workSocket.Close();
}
catch (Exception)
{
}
return;
}
}
}
And my SocketStateObject:
public class SocketStateObject
{
public Socket workSocket = null;
public const int BUFFER_SIZE = 1024;
public byte[] buffer = new byte[BUFFER_SIZE];
public StringBuilder sb = new StringBuilder();
}
** EDIT **
I have updated the code with some suggestions from Chris Taylor.
Just looking at the code quickly, I suspect that you might stop enquing your AsyncReads because s.Available is returning 0, I am refering to the following code
if (read > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
if (s.Available > 0)
{
s.BeginReceive(state.buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(Read), state);
return;
}
}
To confirm, change the above to the following
if (read > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
SocketStateObject nextState = new SocketStateObject();
nextState.workSocket = s;
s.BeginReceive(state.buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(Read), nextState);
}
This is not the complete correction of the code, but it will confirm if this is the problem. You need to make sure that you are closing your sockets correctly etc.
Update
I also noticed that you are sending the socket in as the state in the call to BeginSend.
state.workSocket.BeginSend(answer, 0, answer.Length, SocketFlags.None, new AsyncCallback(Send), state.workSocket);
However, your callback Send is casting the AsyncState to SocketStateObject
SocketStateObject state = (SocketStateObject)iar.AsyncState;
This will be raising InvalidCastExceptions which you are just hiding by adding the empty catch. I am sure others will agree, this is exceptionally bad practice having empty catches it hides so much info that you could be using to debug your problem.
Completely random guess:
http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx
The maximum number of concurrent
connections allowed by a ServicePoint
object. The default value is 2.
You should also note that there is a race condition in your code. In Run(), you wait for allDone before calling BeginAccept again:
while (true)
{
allDone.Reset();
server.BeginAccept(new AsyncCallback(AcceptCon), server);
allDone.WaitOne(); // <------
}
This is fine, however in your AcceptConn callback, the event is set at the top of the method:
private void AcceptCon(IAsyncResult iar)
{
allDone.Set(); // <------
Socket s = (Socket)iar.AsyncState;
Socket s2 = s.EndAccept(iar);
SocketStateObject state = new SocketStateObject();
state.workSocket = s2;
s2.BeginReceive(state.buffer, 0, SocketStateObject.BUFFER_SIZE, 0,
new AsyncCallback(Read), state);
}
The callback will executed by a random thread from the pool, but allDone will be set before anything is actually done. It's entirely possible for your Run() loop to run again in the first thread before the work in AcceptCon actually completes. This will cause you big problems.
You should set allDone after you've performed your initialization (and especially after you've accessed any non-threadsafe class members), like so:
private void AcceptCon(IAsyncResult iar)
{
Socket s = (Socket)iar.AsyncState;
Socket s2 = s.EndAccept(iar);
SocketStateObject state = new SocketStateObject();
state.workSocket = s2;
allDone.Set(); // <------
s2.BeginReceive(state.buffer, 0, SocketStateObject.BUFFER_SIZE, 0,
new AsyncCallback(Read), state);
}
Related
I'm creating a Server Socket in C# for my Unity Application. I have created Asynchronous Server Socket from below link
Asynchronous Server Socket
Using which I can successfully able to connect with client and receive data from client. But after few data received the socket is not receiving data even though the client is sending the data (I'm testing client and server in same machine).
Also there was no exception thrown in try catch either. So I'm not able to identify the root cause.
Please find my code below
public class NetworkStateObject
{
// 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 List<byte> receivedBytes = new List<byte>();
}
private readonly ManualResetEvent allDone = new ManualResetEvent(false);
private readonly ManualResetEvent receiveDone = new ManualResetEvent(false);
private readonly string receiveDelimitter = "<EOF>";
socketThread = new Thread(new ThreadStart(StartSocketServer));
socketThread.Priority = System.Threading.ThreadPriority.BelowNormal;
socketThread.IsBackground = true;
socketThread.Start();
protected void Receive(Socket socket)
{
ReceiveData(socket);
receiveDone.WaitOne();
}
private void ReceiveData(Socket socket)
{
try
{
// Create the state object.
NetworkStateObject state = new NetworkStateObject();
state.workSocket = socket;
// Begin receiving the data from the remote device.
socket.BeginReceive(state.buffer, 0, NetworkStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
NetworkStateObject state = (NetworkStateObject)ar.AsyncState;
Socket socket = state.workSocket;
// Read data from the remote device.
int bytesRead = socket.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));
var bytesArray = state.buffer;
if (bytesRead < NetworkStateObject.BufferSize)
{
Array.Resize(ref bytesArray, bytesRead);
}
var bytesList = new List<byte>(bytesArray);
state.receivedBytes.AddRange(bytesList);
var receivedBytes = state.receivedBytes;
var bytesCount = receivedBytes.Count;
if (receivedBytes.Count > 1)
{
var receivedString = Encoding.ASCII.GetString(receivedBytes.ToArray(), 0, bytesCount);
if (receivedString.IndexOf(receiveDelimitter, StringComparison.CurrentCulture) > -1)
{
var message = receivedString.Replace(receiveDelimitter, String.Empty);
message = Regex.Unescape(message);
socketBaseDelegate.ReceivedMessage(message);
state.receivedBytes.Clear();
receiveDone.Set();
}
else
{
// Get the rest of the data.
socket.BeginReceive(state.buffer, 0, NetworkStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
}
}
else
{
receiveDone.Set();
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
public void ReceivedMessage(string data)
{
socketInputParser.Parse(data);
asynchronousSocketListener.ReceiveMessage();
}
In the above code the ReceiveCallback is not triggered after some time.
Even though client sends data.
else
{
// Get the rest of the data.
socket.BeginReceive(state.buffer, 0, NetworkStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
This part shouldn't be conditional. You should always begin receiving again once the receive callback is complete. Unless of course the connection is terminated.
I am writing some socket server, client application and I have a major problem. My goal is to create an async Server App in C# and a basic client APP in python. When I do follow simple examples both program work. But when I write an async Server with read and write handler messages being send from the client APP, it does not work.
Here is the example Server code that I am using.
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];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3333);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 3333);
// 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(ipLocal);
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);
Console.WriteLine("\n Enters(0)");
if (bytesRead > 0)
{
Console.WriteLine("\n Enters(1)");
// 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
{
Console.WriteLine("\n Detect");
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
Console.WriteLine("\n Enters(1)");
}
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;
}
}
and here is the python code for a simple test client
import socket
HOST, PORT = "127.0.0.1", 3333
data = "data"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
sock.sendall(data)
print data
finally:
sock.close()
As I have inserted some debug code on Server's ReadCallback, I see that the routine is called, but it doesn't process the received data as a message. It doesn't seem to have an endpoint.
Any ideas or solutions will be appreciated.
Your ReadCallback ignores the case when bytesRead == 0, which means the client stopped sending data. If your Python code is actually sending "data" without "<EOF>", then your connection is simply forgotten by the C# server.
Regarding your C# code, there are a few things you could improve:
Use ManualResetEventSlim, it's faster, it doesn't use an operating system handle (unless you actually use the WaitHandle property)
You should handle exceptions from EndAccept in AcceptCallback and EndReceive in ReadCallback, and probably improve exception handling in SendCallback
You're creating a string from your StringBuilder in ReadCallback every time, which goes totally against the purpose of using a StringBuilder; you should parse each string you get from Encoding.ASCII.GetString to search for each character, <, E, O, F and > in succession
// Add to StateObject
public const string EOF = "<EOF>";
public int eofOffset = -1;
public int searchOffset = 0;
// In ReadCallback
string data = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
state.sb.Append(data);
int o = state.searchOffset + state.eofOffset + 1;
while (o < state.sb.Length)
{
if (state.sb[o] != StateObject.EOF[state.eofOffset + 1])
{
state.eofOffset = -1;
state.searchOffset++;
o = state.searchOffset;
}
else
{
state.eofOffset++;
if (state.eofOffset == StateObject.EOF.Length)
{
break;
}
o++;
}
}
// Replace this:
//content = state.sb.ToString();
//if (content.IndexOf("<EOF>") > -1)
// with this:
if (state.eofOffset == StateObject.EOF.Length)
{
// Here is a good place to turn the StringBuilder into a string
// Perhaps truncate data to send back up to state.searchOffset
// ...
}
Not an expert for C#, but I think You have problem with Python program.
try:
sock.connect((HOST, PORT))
sock.sendall("data")
print data
finally:
sock.close()
You're trying to print data, which is not defined. Therefore, except part would be executed (if it existed). Then, program is finished with socket being closed.
I've been working on a socket server program in C# (I was inspired from this post) and my problem is that when a client disconnects an exception "An existing connection was forcibly closed by the remote host" appears when the call EndReceiveFrom() and returns 0, the ref clientEP becomes the client normally close. I don't understand why my DoReceiveFrom() function is called if there is nothing to read. I probably missed something. What is wrong ?
Problem appear there :
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
The full source code:
class UDPServer
{
private Socket serverSocket = null;
private List<EndPoint> clientList = new List<EndPoint>();
private List<Tuple<EndPoint, byte[]>> dataList = new List<Tuple<EndPoint, byte[]>>();
private byte[] byteData = new byte[1024];
private int port = 4242;
public List<Tuple<EndPoint, byte[]>> DataList
{
private set { this.dataList = value; }
get { return (this.dataList); }
}
public UDPServer(int port)
{
this.port = port;
}
public void Start()
{
this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.serverSocket.Bind(new IPEndPoint(IPAddress.Any, this.port));
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
byte[] data = new byte[dataLen];
Array.Copy(this.byteData, data, dataLen);
if (!this.clientList.Any(client => client.Equals(clientEP)))
this.clientList.Add(clientEP);
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
DataList.Add(Tuple.Create(clientEP, data));
}
catch (ObjectDisposedException)
{
}
}
public void SendTo(byte[] data, EndPoint clientEP)
{
try
{
this.serverSocket.SendTo(data, clientEP);
}
catch (System.Net.Sockets.SocketException)
{
this.clientList.Remove(clientEP);
}
}
public void SendToAll(byte[] data)
{
foreach (var client in this.clientList)
{
this.SendTo(data, client);
}
}
public void Stop()
{
this.serverSocket.Close();
this.serverSocket = null;
this.dataList.Clear();
this.clientList.Clear();
}
}
Exception:
An existing connection was forcibly closed by the remote host
Update:
I tried to run my client (netcat) on another pc and the exception no longer appears, even when SendTo(), which is also problematic to delete my client in my clientList.
I still do not understand what is happening.
Everything is as it should be.
This is the way all Async methods work: you invoke BeginDo() and pass into it your implementation of AsyncCallback delegate (in your example that's DoReceiveFrom). You implementation starts executing immediately after that - BeginDo() is not a blocking call.
Inside your implementation, you must call EndDo(), which will block until one of two things happen: the object, on which you invoked BeginDo(), actually does something, or it throws an exception doing it. As it does in your case when client disconnects.
The source on the Async method.
What you need to do for the whole thing to work is
Make sure that you handle that client-disconnected exception properly
Make sure that you call BeginReceiveFrom regardless of the way EndReceiveFrom finishes. And preferably, call BeginReceiveFrom immediately after you call EndReceiveFrom. This is needed because while you server is in-between those calls, it does not actually listen to the socket.
I would put another try-catch around EndReceiveFrom.
UPDATE:
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = 0;
byte[] data = null;
try
{
dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
data = new byte[dataLen];
Array.Copy(this.byteData, data, dataLen);
}
catch(Exception e)
{
}
finally
{
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
if (!this.clientList.Any(client => client.Equals(clientEP)))
this.clientList.Add(clientEP);
DataList.Add(Tuple.Create(clientEP, data));
}
catch (ObjectDisposedException)
{
}
}
Hi stack overflow members.
I'm struggling with some simple code but I can't get it done.
I have this asynchronous server which waits for connections.
while (clientSocket.Connected)
{
try
{
clientSocket.BeginReceive(so.buffer, 0, 200, SocketFlags.None
, new AsyncCallback(wait),so);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
where so(shorted StateObject) it's my class:
internal class StateObject
{
public TcpClient client;
public byte[] buffer;
public StateObject()
{
buffer = new byte[200];
client = new TcpClient();
}
}
I use this class to put out the information on the callback function. However I get the system lacked sufficient buffer space or because a queue was full.
I posted a short piece from the actual program.
One interesting issue, is that if I write:
while (clientSocket.Connected)
{
try
{
byte[] buffer = new byte[200];
clientSocket.BeginReceive(buffer, 0, 200, SocketFlags.None
, new AsyncCallback(wait),so);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
it will work, but I will not be able to pull out the buffer from the asynchronous function(wait).
I'm struggling with this and I can't find answers.
The while loop shouldn't be there, just call beginreceive after the endreceive.
This is a poor example, but may give you some ideas:
public class AsyncTCP
{
public void StartReceive()
{
byte[] buffer = new byte[200];
clientSocket.BeginReceive(buffer, 0, 200, SocketFlags.None, (state) =>
{
int bytesReceived = clientSocket.EndReceive(state);
// handle buffer.
if(bytesReceived != 0)
StartReceive();
} ,so);
}
}
If it's about getting the state within the EndReceive handler:
private void StartReceive()
{
StateObject myState = new StateObject();
myState.buffer = new byte[200];
myState.client = _client; // or whatever
myState.client.BeginReceive(so.buffer, 0, 200, SocketFlags.None, new AsyncCallback(wait),myState);
}
private void EndReceive(IAsyncResult result)
{
StateObject myState = (StateObject)result.State;
int bytesReceived = myState.client.EndReceive(result);
// handle myState.buffer
StartReceive();
}
I think there are better ways to do this, like:
- only constructing a receive buffer ones.
- put some packet header/data with lengths in it.
Good luck
How about using some TPL functions. So your code can be simplified a lot
int readBytes = await s.ReceiveTaskAsync(buffer, 0, buffer.Length);
This is the extension method ReceiveTaskAsync
public static class SocketExtensions
{
public static Task<int> ReceiveTaskAsync(this Socket socket, byte[] buffer, int offset, int count)
{
return Task.Factory.FromAsync<int>(
socket.BeginReceive(buffer, offset, count, SocketFlags.None, null, socket),
socket.EndReceive);
}
}
The problem is here
while (clientSocket.Connected)//checks connected
{
try
{
clientSocket.BeginReceive(so.buffer, 0, 200, SocketFlags.None, new AsyncCallback(wait),so);//says begin receive and continues to do endlessly
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
You've to call BeginReceive again only after you received the data.
Here's and example from msdn how to do that.
I resolved my previous problem(I just needed to remove the while loop, however I messed it up with some code from a synchronous server).
Now I have another problem, so I will use this same thread.
From what I've searched, and understood, you can open an asynchronous server with BecinAccept like this(main method):
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 8082);
TcpListener tcpListener = new TcpListener(IPAddress.Any, 8082);
server = tcpListener.Server;
server.Bind(ipEndPoint);
server.Listen(4);
server.BeginAccept(new AsyncCallback(beginConnection), server);
Then:
static void beginConnection(IAsyncResult iar)
{
Console.WriteLine("Client connected");
Socket s = (Socket)iar.AsyncState;
server = s.EndAccept(iar);
server.Listen(4); // this line was initially absent
server.BeginAccept(beginConnection, s);
}
I want to be able to connect to this server multiple clients.
However, when I try to do this, only the first client connects itself.
The client it's a simple socket, which just echoes back from the server, what we read from the console.
I thought that since in the main method I've called server.Listen(4), I will be able to connect 4 clients.
Then I thought of calling recursively BeginAccept in the beginConnection method.
And last, I received the error, that I must call first the Listen method, so I added that too.
Still no luck.
I have been trying to get this asynchronous UDP server working for the past two days and am banging my head against the wall now.
I am currently running into getting a SocketException for 10057 when I am trying to get RemoteEndPoint from the Socket in the ReceiveCallback.
When looking with the debugger socket is filled, state is filled. LocalEndPoint is normally set to {0.0.0.0:53}, yet RemoteEndPoint says a SocketException was thrown. And I do not understand what I am missing in my set up. Any helps, tips, guidance welcome.
namespace UDPServer
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class StateObject
{
// Client socket
public Socket socket = null;
// Size of the receive buffer
public const int BufferSize = 1024;
// Receive buffer
public byte[] buffer = new byte[BufferSize];
}
public class ServerAsync
{
private static int portNumber = 53;
public static ManualResetEvent WaitEvent = new ManualResetEvent(false);
public static void StartListening()
{
// Data buffer
byte[] bytes = new byte[1024];
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, portNumber);
EndPoint client = new IPEndPoint(IPAddress.Any, 0);
socket.Bind(localEndPoint);
Console.WriteLine("Listening for UDP queries on port 53");
while (true)
{
// Set event to non-signaled state.
WaitEvent.Reset();
Console.WriteLine("Waiting for a connection...");
StateObject state = new StateObject();
state.socket = socket;
socket.BeginReceiveFrom(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, ref client, new AsyncCallback(ReceiveCallback), state);
// Wait until a connection is made before continuing.
WaitEvent.WaitOne();
}
}
public static void ReceiveCallback(IAsyncResult ar)
{
// Signal main thread to continue.
WaitEvent.Set();
int bytesRead = 0;
try
{
if (ar.IsCompleted)
{
StateObject state = (StateObject)ar.AsyncState;
Socket socket = state.socket;
IPEndPoint sender = (IPEndPoint)socket.RemoteEndPoint;
EndPoint remoteEndPoint = (EndPoint)sender;
bytesRead = socket.EndReceiveFrom(ar, ref remoteEndPoint);
if (bytesRead > 0)
{
Console.WriteLine("Received {0} bytes from {1}:{2}: {3}", bytesRead, sender.Address.ToString(), sender.Port.ToString(), BitConverter.ToString(state.buffer));
socket.BeginReceiveFrom(state.buffer, 0, StateObject.BufferSize, 0, ref remoteEndPoint, new AsyncCallback(ReceiveCallback), state);
}
}
}
catch (SocketException se)
{
Console.WriteLine("SocketException: " + se.ErrorCode + ": " + se.Message);
}
catch (ObjectDisposedException ode)
{
Console.WriteLine("Socket closed: " + ode.Message);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Server starting up...");
StartListening();
}
}
}
Why is your main thread looping and reading from the port when the EndCallback is also starting a new read? It looks to me like two threads will be trying to read from the port simultaneously, using the same StateObject.
Also, your receive callback is using the AsyncResult's buffer to start a new read operation. Do you know what the socket does with the AsyncResult object after you return? Can you be sure it doesn't dispose it? You may need to create a new AsyncResult for each read request so that they remain truly independent.