I'm developing a Server application which will receive messages and respond. Nothing really new. So, actually I'm following this answer and this post, but I can't get the AcceptAsync()
method to fire the Completed
event. Searched everywhere on internet, tried similar problem's solutions, but nothing seems to work for me.
I've also tried to call server.Start()
from a Task.Run()
, but no luck. I know the server is listening fine because I can see it on netstat -an
, I'm also able to connect using telnet if I break after Listen()
.
From what I've understood, if AcceptAsync()
method returns true, it'll raise SocketAsyncEventArgs.Completed
event which in turn will call again StartAccept()
method and will loop until I force quit.
The SocketAsyncEventArgs.Completed
is right also: http://prntscr.com/8l3x8p, but still doesn't work.
Here is my piece of code:
public class TTSServer
{
private Socket m_serverSocket;
private IPEndPoint m_serverEndPoint;
[DefaultValue(39454)]
public int Port { get; set; }
[DefaultValue(100)]
public int IncommingQueueSize { get; set; }
[DefaultValue(512)]
public int BufferSize { get; set; }
//Listeners to hold event when something happens.
public static void Main(string[] args)
{
TTSServer server = new TTSServer(39454, 100, 512);
server.Start();
}
public TTSServer(int port, int queueSize, int bufferSize)
{
Port = port;
IncommingQueueSize = queueSize;
BufferSize = bufferSize;
}
public void Start()
{
Console.WriteLine("Starting TTS Server (Port: {0}, QueueSize: {1}, BufferSize: {2})", Port, IncommingQueueSize, BufferSize);
m_serverEndPoint = new IPEndPoint(IPAddress.Any, Port);
m_serverSocket = new Socket(m_serverEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("Binding ({0})", m_serverEndPoint.ToString());
m_serverSocket.Bind(m_serverEndPoint);
Console.WriteLine("Listening");
m_serverSocket.Listen(IncommingQueueSize);
StartAccept(null);
}
public void Stop()
{
}
/// <summary>
/// Receive a incomming connection attemp in an asynchronous way.
/// </summary>
/// <param name="socketEvent">If is null, a new object is created, else, it'll be used for cache friendly reason.</param>
private void StartAccept(SocketAsyncEventArgs socketEvent)
{
//If received reference points to null, let's create a new object.
if (socketEvent == null)
{
Console.WriteLine("Accepting new connections...");
socketEvent = new SocketAsyncEventArgs();
socketEvent.Completed += AcceptCompleted; //Add a callback on completed accept incomming connections attemp.
}
else
{
//Clear current incomming connection socket, so object may be reused.
socketEvent.AcceptSocket = null;
}
//If there is an incomming connection pending(pooled), this method will receive the connection in a async way (witch returns true)
//and will call SocketAsyncEventArgs.Completed callback when done.
//Else, it waits for a new connection, returns false, and don't won't SocketAsyncEventArgs.Completed callback when done, so we have to
//call it manually.
bool async = true;
//When I debug this code, async receive true from AcceptAsync.
async = m_serverSocket.AcceptAsync(socketEvent);
if (!async)
{
AcceptCompleted(this, socketEvent);
}
}
/// <summary>
/// Handles a incomming connection after it's fully received. This function will do the business logic for incomming connections and prepare
/// to receive data.
/// </summary>
/// <param name="sender">Object who posted this function</param>
/// <param name="socketEvent">Information of the incomming connection</param>
private void AcceptCompleted(object sender, SocketAsyncEventArgs socketEvent)
{
Connection connection = new Connection(this, socketEvent.AcceptSocket, BufferSize);
SocketAsyncEventArgs connectedSocketEvent = new SocketAsyncEventArgs();
connectedSocketEvent.UserToken = connection;
//Add a receive callback, to be called whenever the Receive function is finished.
connectedSocketEvent.Completed += FlushBuffer;
ReceiveData(connectedSocketEvent);
//Accept next incomming connection.
StartAccept(socketEvent);
}
Don't know why, the AcceptCompleted
is never fired, even when the AcceptAsync()
method returns true
.