C# 为什么Socket.acceptsync不是';t触发SocketAsyncEventArgs已完成事件?
我正在开发一个服务器应用程序,它将接收消息并做出响应。没什么新鲜事。因此,实际上我正在跟踪和,但我无法使用C# 为什么Socket.acceptsync不是';t触发SocketAsyncEventArgs已完成事件?,c#,sockets,asyncsocket,iocp,C#,Sockets,Asyncsocket,Iocp,我正在开发一个服务器应用程序,它将接收消息并做出响应。没什么新鲜事。因此,实际上我正在跟踪和,但我无法使用acceptsync()方法触发已完成的事件。在互联网上到处搜索,尝试过类似问题的解决方案,但对我来说似乎什么都不管用 我还尝试从任务.Run()调用服务器.Start(),但没有成功。我知道服务器正在监听,因为我可以在netstat-an上看到它,如果在Listen()之后中断,我也可以使用telnet进行连接 据我所知,如果acceptsync()方法返回true,它将引发SocketA
acceptsync()
方法触发已完成的事件。在互联网上到处搜索,尝试过类似问题的解决方案,但对我来说似乎什么都不管用
我还尝试从任务.Run()
调用服务器.Start()
,但没有成功。我知道服务器正在监听,因为我可以在netstat-an
上看到它,如果在Listen()
之后中断,我也可以使用telnet进行连接
据我所知,如果acceptsync()
方法返回true,它将引发SocketAsyncEventArgs.Completed
事件,该事件将再次调用StartAccept()
方法,并将循环直到我强制退出
SocketAsyncEventArgs.Completed
也正确:,但仍然不起作用
以下是我的代码:
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);
}
公共类TTS服务器
{
专用套接字m_serverSocket;
专用IPEndPoint m_服务器端点;
[默认值(39454)]
公共int端口{get;set;}
[默认值(100)]
public int IncommingQueueSize{get;set;}
[默认值(512)]
public int BufferSize{get;set;}
//侦听器在事件发生时保持事件。
公共静态void Main(字符串[]args)
{
TTSServer服务器=新的TTSServer(3945410512);
server.Start();
}
公共TTSServer(int端口、int队列大小、int缓冲大小)
{
端口=端口;
IncommingQueueSize=队列大小;
缓冲大小=缓冲大小;
}
公开作废开始()
{
WriteLine(“启动TTS服务器(端口:{0},队列大小:{1},缓冲大小:{2})”,端口,输入队列大小,缓冲大小);
m_serverEndPoint=新的IPEndPoint(IPAddress.Any,端口);
m_serverSocket=新套接字(m_serverEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
WriteLine(“Binding({0})”,m_serverEndPoint.ToString();
绑定(m_serverEndPoint);
控制台。写线(“监听”);
m_serverSocket.Listen(输入队列大小);
startacept(空);
}
公共停车场()
{
}
///
///以异步方式接收输入连接尝试。
///
///如果为null,则创建一个新对象,否则,将出于缓存友好的原因使用它。
私有void StartAccept(SocketAsyncEventArgs socketEvent)
{
//如果收到的引用点为null,那么让我们创建一个新对象。
if(socketEvent==null)
{
Console.WriteLine(“接受新连接…”);
socketEvent=新的SocketAsyncEventArgs();
socketEvent.Completed+=AcceptCompleted;//在已完成的accept输入连接尝试上添加回调。
}
其他的
{
//清除输入连接插座的电流,以便重新使用该对象。
socketEvent.AcceptSocket=null;
}
//如果有一个输入连接挂起(池),此方法将以异步方式接收连接(witch返回true)
//并将调用SocketAsyncEventArgs。完成后完成回调。
//否则,它将等待一个新连接,返回false,并且不将SocketAsyncEventArgs.Completed回调完成,因此我们必须
//手动调用它。
bool async=true;
//调试此代码时,async从AcceptSync接收true。
async=m_serverSocket.acceptsync(socketEvent);
如果(!异步)
{
AcceptCompleted(此为socketEvent);
}
}
///
///在完全接收到输入连接后处理输入连接。此函数将执行输入连接的业务逻辑并准备
///接收数据。
///
///发布此函数的对象
///输入连接的信息
私有void AcceptCompleted(对象发送方,SocketAsyncEventArgs socketEvent)
{
连接连接=新连接(此,socketEvent.AcceptSocket,BufferSize);
SocketAsyncEventArgs connectedSocketEvent=新的SocketAsyncEventArgs();
connectedSocketEvent.UserToken=连接;
//添加接收回调,在接收函数完成时调用。
connectedSocketEvent.Completed+=FlushBuffer;
接收数据(已连接的SocketEvent);
//接受下一个输入连接。
StartAccept(socketEvent);
}
不知道为什么,AcceptCompleted
永远不会被触发,即使acceptsync()
方法返回true
,编辑:在服务器后放置一行代码。从您的示例开始
一时兴起,你会考虑改变一条线吗?
改变这个
socketEvent.Completed += AcceptCompleted; //Add a callback on completed accept incomming connections attemp.
对此
socketEvent.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptCompleted); //Add a callback on completed accept incomming connections attemp.
socketEvent.Completed+=neweventhandler(AcceptCompleted);//在完成的accept incommming connections尝试上添加回调。
根本原因似乎是默认缓冲:
可选地,可以提供一个缓冲区,在ConnectAsync
方法成功后,在其中接收套接字上的初始数据块。在这种情况下,需要将SocketAsyncEventArgs.buffer
属性设置为包含要接收的数据和SocketAsyncEventArgs.Count
pr的缓冲区属性需要设置为要在缓冲区中接收的最大数据字节数。可以使用SocketAsyncEventArgs.SetBuffer
方法设置这些属性。传入的缓冲区的一部分将在内部使用,以供基础WinsockAcceptEx
调用使用。这意味着返回的数据量将减少始终小于提供的System.Net.Sockets.SocketAsyncEventArgs
实例上的SocketAsyncEventArgs.Count
属性的值。amo
SocketAsyncEventArgs args = ...;
args.SetBuffer(null, 0, 0);