如何通过TCP连接C#阻止我的程序冻结

时间:2017-11-19 23:20:51

标签: c# tcp

我已经创建了一个TCP客户端并且连接正常但是有点困惑如何在不关闭连接的情况下从服务器接收消息?

我目前的方法是在网络流读取方法上运行一个协同例程,但这会冻结我的程序,所以它显然是错误的方法所以我不确定如何解决它。

我想让连接保持活动状态,并在邮件从服务器到达时读取邮件。

这是我目前设置的内容:

Deck::Deck(int cardSize, int cardCount, int numberMax){
    int randInt;
    int size = cardSize * cardSize;
    vector<vector<int>> deckArr(cardCount);
    for(int t = 0; t < cardCount; t++){
        vector<int> arr(size);
        for(int i = 0; i < size; i++){
            randInt = computeRandInt(numberMax, cardSize);
            if(arr[i] == 0) arr[i] = randInt;
            else if (randInt != arr[i-1]) arr[i] = randInt;
        }
        deckArr.push_back(arr);
    }
}

这是接收方法的代码:

// the idea is to run a coroutine for recieving messages
private IEnumerator<float> _RunTCPSocket()
{
    int timer = DateTime.Now.Second;
    byte[] readBuffer = new byte[1024];

    while (SocketManager.IsConnected)
    {
        // this is the keep alive packets to server to prevent timeout on server side
        if (DateTime.Now.Second - timer > KeepAliveRate)
        {
            Debug.Log("Sending");
            timer = DateTime.Now.Second;
            SocketManager.Send(null);
        }

        int msgLength = SocketManager.Recieve(readBuffer); 
        if (msgLength > 0)
            Debug.Log(Encoding.ASCII.GetString(readBuffer, 0, msgLength));

        yield return Timing.WaitForOneFrame;
    }
}

如何阻止此程序锁定?

1 个答案:

答案 0 :(得分:1)

您可以使用开始/结束方法让您的程序负责:

Document from microsoft

您可以看到BeginReceive方法的使用非常复杂,我认为它不易使用。
另一种方法是在Task中调用read / write方法 第三个选项是在客户端使用的TcpClient和在服务器端使用的TcpListener。这两个类只是一个下划线TCP套接字的包装器。使用Stream和Async方法,这些包装器可以让您的生活更轻松。

如果您想了解有关使用C#进行网络编程的更多信息,我非常推荐本书: C#网络编程 Richard Blum

<强>更新

使用任务的代码:

    public event EventHandler<ReceiveDataEventArgs> DataReceived = null;
    public void StartReceive()
    {
        Task.Run(() =>
        {
            while (true)
            {
                var bytesRead = _networkStream.Read(readBuffer, 0, readBuffer.Length);
                DataReceived?.Invoke(this, new ReceiveDataEventArgs
                {
                    Data = bytesRead
                });
            }
        });

    }

    public class ReceiveDataEventArgs : EventArgs
    {
        public byte[] Data { get; set; }
    }