首页 > 解决方案 > 如何从服务器接收数据?

问题描述

我正在用 C# Windows Froms 编写一个聊天应用程序。我的问题是,我的服务器可以向每个连接的客户端发送消息,但只有发送消息的客户端才能收到响应。我试图创建一个像 ReceiveLoop() 这样的函数,里面有一个无限循环,或者添加一个计时器并为每个滴答声调用 Receive() 函数,但由于应用程序崩溃,两者都没有成功。如何实时获取数据?我附上了我客户的应用程序代码。

public partial class Form1 : Form
{
    private string name;
    private Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    private void Namebt_Click(object sender, EventArgs e)
    {
        if (!Test(Nametb.Text)) Nametb.Text = "Nie wpisano nazwy!";
        else
        {
            name = Nametb.Text;
            Nametb.Clear();
            Nametb.Enabled = false;
            Namebt.Enabled = false;
            Messageslb.Enabled = true;
            timer1.Start();
            LoopConnect();
        }
    }

    private void LoopConnect()
    {
        int attempts = 0;
        while (!_clientSocket.Connected)
        {
            try
            {
                attempts++;
                _clientSocket.Connect(IPAddress.Loopback, 100);

            }
            catch (SocketException)
            {
                Messageslb.Items.Clear();
                Messageslb.Items.Add("Connection attempts: " + attempts.ToString());
                Messageslb.Refresh();
            }
        }
        Messageslb.Items.Add("Connected!");
        Messageslb.Refresh();
        Messagetb.Enabled = true;
        Sendbt.Enabled = true;
    }

    private bool Test(string text)
    {
        if (text != "") return true;
        return false;
    }

    private void Sendbt_Click(object sender, EventArgs e)
    {
        if (!Test(Messagetb.Text)) Messagetb.Text = "Nie wpisano zadnej wiadomosci!";
        else
        {
            Send();
        }
    }
    private void Receive()
    {
        if(_clientSocket.ReceiveBufferSize > 0)
        {
            byte[] receivedBuffer = new byte[1024];
            int rec = _clientSocket.Receive(receivedBuffer);
            byte[] data = new byte[rec];
            Array.Copy(receivedBuffer, data, rec);
            Messageslb.Items.Add(Encoding.ASCII.GetString(data));
        }         
    }

    private void Send()
    {
        string message = "[" + name + "]: " + Messagetb.Text;
        Messagetb.Clear();
        byte[] buffer = Encoding.ASCII.GetBytes(message);
        _clientSocket.Send(buffer);
        Receive();
    }

    private void Nametb_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Return) Namebt_Click(sender, e);
    }

    private void Messagetb_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Return) Sendbt_Click(sender, e);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Receive();
    }
}

标签: c#.netsocketstcpsystem.net

解决方案


您需要在单独的任务上运行接收方法。

_clientSocket.Receive(receivedBuffer);

应该:

private Task _receiving;
private void Receive()
{
  if(_clientSocket.ReceiveBufferSize > 0)
    {

    if(_receiving == null || _receiving.IsCompleted)
     _receiving = Task.Run(() => 
     {
        byte[] receivedBuffer = new byte[1024];
        int rec = _clientSocket.Receive(receivedBuffer);
        byte[] data = new byte[rec];
        Array.Copy(receivedBuffer, data, rec);
        Messageslb.Items.Add(Encoding.ASCII.GetString(data)); 
     });

 }
}

否则 clientSocket.Receive 会挂起你的程序。

不过,您需要确保 Messageslb 是线程安全的,这需要进一步研究。

如果您正在寻找实时通信,请查看 C# 的 RTC 客户端https://msdn.microsoft.com/en-us/library/ms946701.aspx。否则我会强烈推荐 Socket.IO,因为它使用起来非常简单,而且设置起来非常快 rtc!https://socket.io/get-started/chat


推荐阅读