如何从服务器接收数据?

时间:2019-01-07 21:21:28

标签: c# .net sockets tcp system.net

我正在使用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();
    }
}

1 个答案:

答案 0 :(得分:0)

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

_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#https://msdn.microsoft.com/en-us/library/ms946701.aspx的RTC Client。否则,我强烈推荐Socket.IO,因为它使用起来非常简单,并且可以通过非常快速的rtc进行设置! https://socket.io/get-started/chat