TCP 套接字服务器 Windows 应用程序

发布于 2024-12-13 10:48:53 字数 2514 浏览 1 评论 0原文

我目前有一个 Windows 应用程序,它使用 TCP 套接字连接用户并发送/接收数据。当新用户尝试连接而其他几个用户(用户数量不同)已经连接并接收数据时,应用程序会崩溃。我的应用程序需要从一个人接收数据并将其发送给许多用户。应用程序每秒接收几次数据。

我的代码在错误发生之前所做的最后一件事是尝试将新客户端添加到列表中。似乎当尝试连接新用户时,它会干扰尝试发送的数据。

private static void EndAccept(IAsyncResult ar)
{
    Listener_Socket = (Socket)ar.AsyncState;
    ClientsList.Add(Listener_Socket.EndAccept(ar));
    Listener_Socket.BeginAccept(new AsyncCallback(EndAccept), Listener_Socket);
    ...
    AsyncCallback receiveData = new AsyncCallback(MyServer.OnReceivedData);
}

事件查看器错误:

应用程序:xxxxxxxxxxxx.exe 框架版本:v4.0.30319 描述:由于未处理的异常,进程被终止。 异常信息:System.InvalidOperationException 堆栈:位于 System.Collections.ArrayList+ArrayListEnumeratorSimple.MoveNext() 在 MyServer.OnRecievedData(System.IAsyncResult) 在 System.Net.LazyAsyncResult.Complete(IntPtr) 处 System.Threading.ExecutionContext.runTryCode(System.Object) 位于 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode、System.Object)位于 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback、System.Object、布尔值)位于 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback、System.Object)位于 System.Net.ContextAwareResult.Complete(IntPtr) 位于 System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32, UInt32、System.Threading.NativeOverlapped*) 在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32,System.Threading.NativeOverlapped *)

OnRecievedData:

private static void OnRecievedData(IAsyncResult ar)
    {
        SocketClient client = (SocketClient)ar.AsyncState;
        byte[] aryRet = client.GetRecievedData(ar);

        if (aryRet.Length < 1)
        {
            client.ReadOnlySocket.Close();
            ClientsList.Remove(client);
            return;
        }
        foreach (SocketClient clientSend in ClientsList)
        {
            if (client != clientSend)
                try
                {
                    clientSend.ReadOnlySocket.NoDelay = true;
                    clientSend.ReadOnlySocket.Send(aryRet);
                }
                catch
                {
                    clientSend.ReadOnlySocket.Close();
                    ClientsList.Remove(client);
                    return;
                }
        }
        client.SetupRecieveCallback();
    }

I currently have a Windows Application that uses TCP Sockets to connect users and send/receive data. The application crashes when a new user tries to connect while several other users (never the same amount of users) are already connected and receiving data. My application needs to receive data from one person and send it out to many users. The application receives data couple times a second.

The last thing my code does before error error is trying to add a new client to the list. It seems like when trying to connect a new user it is interfering with the data attempting to be sent.

private static void EndAccept(IAsyncResult ar)
{
    Listener_Socket = (Socket)ar.AsyncState;
    ClientsList.Add(Listener_Socket.EndAccept(ar));
    Listener_Socket.BeginAccept(new AsyncCallback(EndAccept), Listener_Socket);
    ...
    AsyncCallback receiveData = new AsyncCallback(MyServer.OnReceivedData);
}

Event Viewer Error:

Application: xxxxxxxxxxxx.exe Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.InvalidOperationException Stack: at
System.Collections.ArrayList+ArrayListEnumeratorSimple.MoveNext() at
MyServer.OnRecievedData(System.IAsyncResult)
at System.Net.LazyAsyncResult.Complete(IntPtr) at
System.Threading.ExecutionContext.runTryCode(System.Object) at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode,
CleanupCode, System.Object) at
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object, Boolean) at
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object) at
System.Net.ContextAwareResult.Complete(IntPtr) at
System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32,
UInt32, System.Threading.NativeOverlapped*) at
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32,
UInt32, System.Threading.NativeOverlapped*)

OnRecievedData:

private static void OnRecievedData(IAsyncResult ar)
    {
        SocketClient client = (SocketClient)ar.AsyncState;
        byte[] aryRet = client.GetRecievedData(ar);

        if (aryRet.Length < 1)
        {
            client.ReadOnlySocket.Close();
            ClientsList.Remove(client);
            return;
        }
        foreach (SocketClient clientSend in ClientsList)
        {
            if (client != clientSend)
                try
                {
                    clientSend.ReadOnlySocket.NoDelay = true;
                    clientSend.ReadOnlySocket.Send(aryRet);
                }
                catch
                {
                    clientSend.ReadOnlySocket.Close();
                    ClientsList.Remove(client);
                    return;
                }
        }
        client.SetupRecieveCallback();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅笑依然 2024-12-20 10:48:53

当客户端连接时,EndAccept 通常会在运行 OnRecievedData 的线程之外的另一个线程上调用。如果 EndAccept 发生在 foreach 的中间,则枚举器不再有效(集合已更改)。

您应该使用某种同步机制(例如lock)来防止这种情况发生。

我什至错过了苏哈斯提到的;该集合也是在同一线程内修改的。

When a client connects, EndAccept will usually be invoked on another thread than the thread OnRecievedData is running on. If EndAccept happens in the middle of the foreach, the enumerator is no longer valid (the collection has changed).

You should use some kind of synchronization mechanism like lock to prevent this from happening.

And I even missed what Suhas mentions; the collection is modified from within the same thread, too.

初心未许 2024-12-20 10:48:53

一种可能性 - 当您迭代该列表时,您不应该修改该列表。在上面的示例中,您要从 ClientsList 上的 foreach 循环内的 ClientsList 中删除项目

A possibility - You should not modify a list when you are iterating that list. In your example above you are removing item from ClientsList inside the foreach loop on ClientsList

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文