I wrote my code using this article at msdn as a primary helper
My code:
private ManualResetEvent _AllDone = new ManualResetEvent(false);
internal void Initialize(int port,string IP)
{
IPEndPoint _Point = new IPEndPoint(IPAddress.Parse(IP), port);
Socket _Accpt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Accpt.Bind(_Point);
_Accpt.Listen(2);
while (true)
{
_AllDone.Reset();
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
_AllDone.WaitOne(); <<crash here
}
}
This is what happens,I set a breakpoint at BeginAccept(I thought there's the problem),but it steps it normally.However,when I try to step "_AllDone.WaitOne()" - the server crash.
If _allDone can't be used in a win32 form application - how do I make my project?
EDIT
I forgot to mention I wrote _AllDone.Reset() in Accept(),but It doesn't go there,I set a breakpoint there,but it won't go.
private void Accept(IAsyncResult async)
{
_AllDone.Set();
Socket _Accpt = (Socket)async.AsyncState;
Socket _Handler = _Accpt.EndAccept(async);
StateObject _State = new StateObject();
_State.workSocket = _Handler;
_Handler.BeginReceive(_State.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), _State);
}
So if I get it right, you want to re-start Accept as soon as a socket connection is received, and not wait until Accept is done, and that's why you don't use the sync version of Accept.
So you are saying that it does not fire your Accept method when you connect a socket to the specified address and port? Because that's what Accept does: it accepts a new incoming connection, waiting until a client connects. So that may be why you are thinking that it "crashed" and why it never reaches your code in your Accept method.
Hint: maybe also have a look at Socket.AcceptAsync
Edit: To set up an async server listening to incoming connections, you don't need any ManualWaitEvent:
internal void Initialize(int port,string IP) {
IPEndPoint _Point = new IPEndPoint(IPAddress.Parse(IP), port);
Socket _Accpt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Accpt.Bind(_Point);
_Accpt.Listen(2);
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
}
private void Accept(IAsyncResult async) {
Socket _Accpt = (Socket)async.AsyncState;
Socket _Handler;
try {
_Handler = _Accpt.EndAccept(async);
} finally {
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
}
StateObject _State = new StateObject();
_State.workSocket = _Handler;
_Handler.BeginReceive(_State.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), _State);
}
Note: You will also need an exit condition, so that the BeginAccept is not called (for instance when you want to shut down the server).
I think that Lucero is trying to say, that the application works normally, you may ask how come.
Well when you are using a server side socket application, what you basically do is to ask the server to liseten to a port and wait for a conection to arrive. when the connection arrives then you do the rest of the code.
What Lucero was saying is, that while no message is arriving to the server the server keeps lisetning and waiting, which might look for you as if it's freezes.
Is it the case in your code?
Related
I have a socket that serves a single request-response purpose.
I set it up on port XXX let it wait for a connection, read the data and reply with some data.
I would like to open a new socket on the same port. As soon as the response was sent.
That is handled externally (there is a manager that is checking the state of the thread and if it was used it disposes it and creates a new one.
The problem is that it gets blocked on
_socket = _socket.Accept();
and when a new client tries to connect it never leaves this line. (And client gets no reply).
The socket is running in
new Thread(Run);
and here is my Run method:
private void Run()
{
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, Port);
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
_socket = _socket.Accept();
var data = string.Empty;
while (true)
{
var bytes = new byte[1024];
var bytesRec = _socket.Receive(bytes);
data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>", StringComparison.Ordinal) <= -1) continue;
var dataWithoutEof = data.Substring(0, data.IndexOf("<EOF>", StringComparison.Ordinal));
//TODO: do smt with the data
break;
}
var byteData = Encoding.UTF8.GetBytes("testResponse" + "<EOF>");
_socket.Send(byteData);
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
I suppose that I am not closing the existing socket correctly.
You code is wrong you should not expect this method to exit because you want your server up and running the whole time. I am assuming here you call run several times. Don't do that.
The code becomes then something like this :
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
while (true)
{
var _servicingsocket = _socket.Accept();
....
_servicingsocket.close();
}
accept is a blocking call. That waits for a new connection.
_socket is a listening socket and must be kept during the lifetime of the server.
A TCP connection is based on the notion of a socket pair.
When the server starts you have a single socket that listens on port 100.
Suppose a connection is established, then accept returns what is called a servicing socket that is basically a clone from the listening socket. This means that it is also using source port 100, but because it is a servicing socket it belongs to a socket pair that identifies the connection. A socket pair is the combination of 2 sockets, your own socket and the peer. When a data comes in, TCP will iterate through the socket pairs to find the right socket.
An additional advantage of doing it this way is that you allow other connection attempts to queue up on the listening socket while you are processing the first request. Your _socket is overwritten with the servicing socket and you are then assuming that the listening socket is going to be garbage collected. I am not sure if this is going to happen because I haven't tried it like you are doing it in your code because it is a bad idea in the first place because it implements idisposable. (https://msdn.microsoft.com/en-us/library/system.net.sockets.socket%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) If you really want to close the server you have to make sure to close both the servicing socket and the listening socket to make the code clean.
I am trying to implement a simple TCP server and I basically copied the example on MSDN sans a couple of lines and tried to make it work. I have an external client trying to connect already.
This is my code:
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList[0], 4001);
Socket listener = new Socket(localEP.Address.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEP);
listener.Listen(1000);
while (true)
{
listener.BeginAccept(new AsyncCallback(AcceptCnxCallback), listener);
}
}
catch (Exception e)
{
//Log here
}
This is my callback:
private void AcceptCnxCallback(IAsyncResult iar)
{
MensajeRecibido msj = new MensajeRecibido();
Socket server = (Socket)iar.AsyncState;
msj.workSocket = server.EndAccept(iar);
}
And this is the information of one of the incoming packages:
TCP:[SynReTransmit #1727889]Flags=......S., SrcPort=57411, DstPort=4001, PayloadLen=0, Seq=673438964, Ack=0, Win=5840 ( Negotiating scale factor 0x4 ) = 5840
Source: 10.0.19.65 Destination: 10.0.19.59
I basically have two issues:
If I use the while loop I get an OutOfMemoryException
I never do manage to connect to the client
Any tips on either of the two problems? Thank you in advance!
Your problem is, that you use asynchronous calls all the time. There is no wait mechanism or similar, so generally you are just creating new asynchronous callbacks in an infinite loop.
For a basic TCP I would recommend to use the simple approach and use the synchronous methods.
Accept() is blocking, so the program flow will stop until there is an ingoing connection.
while (true)
{
Socket s = listener.Accept();
buffer = new byte[BUFFER_SIZE];
s.Receive(buffer);
//Do something
s.Send(...);
}
Noe that this is just a basic example. If you want to keep your connection you might consider a new Thread for each accepted Socket, that continoues with receiving and sending data.
First problem
You are using an infinite loop to call an async method.
try it like this:
listener.BeginAccept(new AsyncCallback(AcceptCnxCallback), listener);
//add your code here (this part will be executed wile the listner is waiting for a connection.
while (true)
{
Thread.Sleep(100);
}
and change the Callbackmethod to:
private void AcceptCnxCallback(IAsyncResult iar)
{
MensajeRecibido msj = new MensajeRecibido();
Socket server = (Socket)iar.AsyncState;
msj.workSocket = server.EndAccept(iar);
//call again the listener after you get a message
listener.BeginAccept(new AsyncCallback(AcceptCnxCallback), listener);
}
I'm opening a UDP Socket for receiving udp packets. However sometimes It never gets to the point Do stuff with data.
Data is being received, I can see it on Wireshark:
but the callback only runs to close the socket when I run the Disconnect code.
private void OpenUDPSocket()
{
this.processDataSockets.Clear();
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
UPDData data = new UPDData();
data.Socket = new Socket(ip.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
data.Socket.Bind(new IPEndPoint(ip, 2222));
data.Socket.EnableBroadcast = true;
data.Buffer = new byte[512];
data.Socket.BeginReceive(data.Buffer, 0, 512, SocketFlags.None, this.ReceivedData, data);
this.processDataSockets.Add(data);
}
this.socketOpen = true;
}
private void ReceivedData(IAsyncResult ar)
{
UPDData data;
try
{
data = (UPDData)ar.AsyncState;
data.Socket.EndReceive(ar);
}
catch (ObjectDisposedException)
{
// The connection has been closed
return;
}
//... Do stuff with data
data.Socket.BeginReceive(data.Buffer, 0, 512, SocketFlags.None, this.ReceivedData, data);
}
When this happens I'm left stuck, restarting the application doesn't help. I need to reboot my machine for the callback to start working again.
I have no idea where to go from here or how to fix this.
Any Ideas what's happening?
In the end we could not resolve this issue. It was not limited to Asynchronous IO or completion ports. Finally we took the work around step of using PcapDotNet to pick up the packets directly, which worked.
Here's my code for a very simple TCP Server (basically the sample Asynchronous Server Socket example - http://goo.gl/Ix5C - modified slightly):
public static void InitiateListener()
{
try
{
allDone = new ManualResetEvent(false);
configFile = new XmlConfig();
StartListening();
}
catch (Exception exc)
{
LogsWriter f = new LogsWriter(configFile.ErrorLogsPath);
f.WriteToFile(exc.Message);
f.CloseFile();
}
}
private static void StartListening()
{
try
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, configFile.Port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception exc)
{
throw exc;
}
}
public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set(); // Signal the main thread to continue.
// 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 hexData = string.Empty;
// Retrieve the state object and the handler socket from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
try
{
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
hexData = BitConverter.ToString(state.buffer);
if (hexData.Contains("FA-F8")) //heartbeat - echo the data back to the client.
{
byte[] byteData = state.buffer.Take(bytesRead).ToArray();
handler.Send(byteData);
}
else if (hexData.Contains("0D-0A")) //message
{
state.AsciiData = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
state.ParseMessage(configFile);
}
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
catch (Exception)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
This is all in a Windows service. And the CPU maxes to 100% after about 2 and a half days of running perfectly acceptably. This has happened 3 times now - the windows service always works fine and functions as it's supposed to, utlizing almost no CPU resources but sometime on the 3rd day goes to 100% and stays there until the service is resarted.
I get very simple CSV packets, that I parse quickly and send it off to a database via a webservice in this method:
state.ParseMessage(configFile);
Even when the CPU is 100%, the database gets filled up pretty reliably. But I understand this could be one place where I need to investigate?
Which other areas of the code seem like they could be causing the problem? I'm new to async programming, so I don't know if I need to close threads manually. Also, this might be another problem:
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
Calling that line within ReadCallback itself. I do this to maintain the connection with the client and continue to receive the data, but maybe I should close to the socket and force a new connection?
Could you please offer some suggestions? Thanks
Instead of loop while(true) in startlistening method we need to call
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
from AcceptCallback method once completion of accepting new client.
You need to detect disconnection through bytesRead == 0. Right now you don't and instead issue another read.
Looks like you have copied MSDN sample code. I can tell because of the insightless combination of async IO and events. All this code becomes simpler when you use synchronous IO.
I am just starting out Socket Programming in C# and am now a bit stuck with this problem.
How do you handle multiple clients on a single server without creating a thread for each client?
The one thread for each client works fine when there are say 10 clients but if the client number goes up to a 1000 clients is creating a thread for every single one of them advisable? If there is any other method to do this can someone please tel me?
Try to use asynchronous server.
The following example program creates a server that receives connection requests from clients. The server is built with an asynchronous socket, so execution of the server application is not suspended while it waits for a connection from a client. The application receives a string from the client, displays the string on the console, and then echoes the string back to the client. The string from the client must contain the string <EOF> to signal the end of the message.
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, 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.
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;
}
}
That's will be the best solution.
Threads can work fine but rarely scales well to that many clients. There are two easy ways and lots of more complex ways to handle that, here's some pseudocode for how the easier two are usually structured to give you an overview.
select()
This is a call to check which sockets have new clients or data waiting on them, a typical program looks something like this.
server = socket(), bind(), listen()
while(run)
status = select(server)
if has new client
newclient = server.accept()
handle add client
if has new data
read and handle data
Which means no threads are needed to handle multiple clients, but it doesn't really scale well either if handle data take a long time, then you won't read new data or accept new clients until that's done.
Async sockets
This is another way of handling sockets which is kind of abstracted above select. You just set up callbacks for common events and let the framework do the not-so-heavy lifting.
function handleNewClient() { do stuff and then beginReceive(handleNewData) }
function handleNewData() { do stuff and then beginReceive(handleNewData) }
server = create, bind, listen etc
server.beginAddNewClientHandler(handleNewClient)
server.start()
I think this should scale better if your data handling take a long time. What kind of data handling will you be doing?
This could be a good starting point. If you want to avoid 1 thread <-> 1 client; then you should use async socket facilities provided in .NET. Core object to use here is SocketAsyncEventArgs.