Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么Socket.acceptsync不是';t触发SocketAsyncEventArgs已完成事件?_C#_Sockets_Asyncsocket_Iocp - Fatal编程技术网

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
方法设置这些属性。传入的缓冲区的一部分将在内部使用,以供基础Winsock
AcceptEx
调用使用。这意味着返回的数据量将减少始终小于提供的
System.Net.Sockets.SocketAsyncEventArgs
实例上的
SocketAsyncEventArgs.Count
属性的值。amo
SocketAsyncEventArgs args = ...;
args.SetBuffer(null, 0, 0);