C#,服务器/客户端聊天的简单问题

时间:2017-10-10 22:48:11

标签: c#

我在C#中有2个项目,一个是服务器,一个是客户端。使用后台工作程序,他们异步聊天。服务器正在发送消息,客户端正在获取它们并正常显示它们,但是如果我从客户端向服务器发送消息,它第一次正常工作,那么它就不再从客户端发送了。之后,尝试从服务器发送到客户端仍然可以正常工作,但客户端将只发送第一条消息。任何人都可以帮我解释原因吗?

编辑: 这个GIF显示了最新发生的事情:https://gyazo.com/ce0803519702d3080ddc57d0ef45ae0c

服务器:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;

    namespace SeaboltServerHw5
    {
public partial class Server : Form
{
    String str;
    TcpListener listen = new TcpListener(IPAddress.Parse("127.0.0.1"), 18888);
    Boolean connected = false;
    StreamReader inn;
    StreamWriter outt;
    Socket sock; 
    NetworkStream stream;
    public Server()
    {
        InitializeComponent();
        serverRun.RunWorkerAsync();      
    }

    private void StartServer()
    {
        listen.Start();
        sock = listen.AcceptSocket();
        connected = true;
        stream = new NetworkStream(sock);
        inn = new StreamReader(stream);
        outt = new StreamWriter(stream);
        outt.AutoFlush = true;
    }

    private void serverRun_DoWork(object sender, DoWorkEventArgs e)
    {
        StartServer();
        if (connected == true)
        {
            str = inn.ReadLine();
        }
        else
            return;
    }

    private void serverRun_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //lblConnect.Text = "Client Connected.";
        rtbData.AppendText("From Client: " + str + "\n");
        serverRun.RunWorkerAsync();
    }

    private void tbEnter_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            String temp = tbEnter.Text;
            outt.WriteLine(temp);
            rtbData.AppendText("From Server: " + temp + "\n");
            tbEnter.Text = "";
        }
        else
            return;
    }


}
  }

客户端:

    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;

   namespace SeaboltClientHW5
   {
public partial class Client : Form
{
    String str;
    Boolean connected = false;
    TcpClient client = new TcpClient();
    NetworkStream stream;
    StreamReader inn;
    StreamWriter outt;
    public Client()
    {
        InitializeComponent();
        client.Connect("127.0.0.1", 18888);
        bgWork.RunWorkerAsync();
    }

    public void startClient()
    {

        connected = true;
        stream = client.GetStream();
        inn = new StreamReader(stream);
        outt = new StreamWriter(stream);
        outt.AutoFlush = true;
    }

    private void bgWork_DoWork(object sender, DoWorkEventArgs e)
    {
        startClient();
        if (connected == true)
        {
            str = inn.ReadLine();
        }
        else
            return;
    }

    private void bgWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        rtbData.AppendText("From Server: " + str + "\n");
        bgWork.RunWorkerAsync();
    }

    private void tbEnter_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            String temp = tbEnter.Text;
            outt.WriteLine(temp);
            rtbData.AppendText("From Client: " + temp + "\n");
            tbEnter.Text = "";
        }
        else
            return;
    }


 }
  }

1 个答案:

答案 0 :(得分:0)

问题是listen.AcceptSocket()(正在等待进入连接)不会被调用一次,而是在每条消息之后调用。一旦 Client 启动并且服务器接受第一条消息,它就会第一次成功。但是它第二次等待无限期(直到新客户端启动)并且服务器被卡住了。

这可能就是你有connected变量的原因 - 但是现在它已经没用了,因为在调用StartServer()之后,条件if (connected == true)将始终为真。为确保首次调用listen.AcceptSocket(),请重写服务器serverRun_DoWork,如下所示:

private void serverRun_DoWork(object sender, DoWorkEventArgs e)
{
    if (!connected)
        StartServer();

    str = inn.ReadLine();
}

也应该对客户端进行类似的更改,但与服务器不同,它不是问题,因为客户端代码调用client.GetStream(),如果重复调用,则立即返回现有网络流,因此尽管调用多余client.GetStream()在每条消息之后,它基本上是无害的。

private void bgWork_DoWork(object sender, DoWorkEventArgs e)
{
    if (!connected)
        startClient();

    str = inn.ReadLine();
}