简单的字符串消息客户端/服务器协议 [英] Simple string messaging client/server protocol

查看:50
本文介绍了简单的字符串消息客户端/服务器协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种在 TCP 中实现用于发送和接收简单字符串消息的协议的方法.我有一个客户端和一个服务器应用程序,当它们第一次开始运行时,我按下客户端上的连接按钮连接到服务器.服务器的列表框中会弹出一些文本,说明客户端已连接,而客户端的列表框中会出现一些文本,说明它已连接到服务器.

I am looking for a way to implement a protocol in TCP for sending and receiving simple string messages. I have a client and a server app and when both start running for the first time I press the connect button on the client to connect to the server. Some text pops up on the server's listbox saying that a client has connected, and on the client's listbox some text appears saying that it is connected to the server.

那部分工作正常,但现在我希望能够将其他字符串发送到服务器,并且根据我发送的字符串将使服务器执行某个操作,我该怎么做?想到的第一个想法是在某处使用 if-then 语句.我将在下面发布我的代码:

That part works ok, but now I want to be able to send other strings to the server and depending on what string I send over would make the server perform a certain operation, how can I do this? First idea that comes to mind is to use if-then statements somewhere. I will post my code below:

服务器:

    private static int port = 8080;
    private static TcpListener listener;
    private static Thread thread;


   private void Form1_Load(object sender, EventArgs e)
    {

        listener = new TcpListener(new IPAddress(new byte[] { 10, 1, 6, 130 }), port);
        thread = new Thread(new ThreadStart(Listen));
        thread.Start(); 


    }

   private void Listen()
    {
        listener.Start();
        listBox1.Invoke(new EventHandler(delegate { listBox1.Items.Add("Listening on: " + port.ToString()); }));


        while (true)
        {              
            listBox1.Invoke(new EventHandler(delegate { listBox1.Items.Add("Waiting for connection...."); }));
            TcpClient client = listener.AcceptTcpClient();
            Thread listenThread = new Thread(new ParameterizedThreadStart(ListenThread));
            listenThread.Start(client);

        }
    }

    //client thread 
    private void ListenThread(Object client)
    {

        NetworkStream netstream = ((TcpClient)client).GetStream();

        listBox1.Invoke(new EventHandler(delegate { listBox1.Items.Add("Request made"); }));


        byte[] resMessage = Encoding.ASCII.GetBytes("Connected to Server");



        netstream.Write(resMessage, 0, resMessage.Length);
        netstream.Flush();

    } 

客户:

 TcpClient tcpclnt;

 private void buttonConnect_Click(object sender, EventArgs e)
    {
        try
        {
            tcpclnt = new TcpClient();
            userEventBox.Items.Add("Connecting.....");

            try
            {

                tcpclnt.Connect("10.1.6.130", 8080);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());


                return;
            }

            Stream stm = tcpclnt.GetStream();

            byte[] bb = new byte[100];
            int k = stm.Read(bb, 0, 100);

            string returndata = System.Text.Encoding.ASCII.GetString(bb);

            userEventBox.Items.Add(returndata);
            tabControl1.Enabled = true;


           //need a way for the server see this string
            string populateList = "Test";

            ASCIIEncoding asen = new ASCIIEncoding();

            byte[] ba = asen.GetBytes(populateList);
            stm.Write(ba, 0, ba.Length);              
        }

        catch (Exception ex)
        {
            Console.WriteLine("Error..... " + ex.StackTrace);
        }
    }

我很困惑,希望您能在此主题上提供任何帮助.谢谢你.

I am quite stuck and would appreciate any help you could provide on this subject. Thank you.

Source -> C# 客户端-服务器协议/模型问题

推荐答案

建立连接后,客户端和服务器都需要持续监视它们的 NetworkStream 对象以获取新数据.接收到数据后,应将其附加到某种数据缓冲区,直到您收到足以构成完整消息的数据.收到适当数量的数据后,您可以尝试从中解析消息并做出适当的响应.

After you've established your connection, both the client and the server need to continuously monitor their NetworkStream objects for new data. When data is received, it should be appended to some kind of data buffer until you've received enough to constitute a complete message. Once you've received the appropriate amount of data, you can attempt to parse the message out of it and respond appropriately.

本质上,您需要设置如下所示的逻辑:

Essentially, you need to set up logic that looks something like this:

var data = new byte[1024];
var dataLength = 0;
var dataBuffer = new MyCustomDataBuffer();
while (true)
{
    while (stream.DataAvailable)
    {
        dataLength = stream.Read(data, 0, data.Length);
        dataBuffer.Append(data, dataLength);
        while (dataBuffer.ContainsCompleteMessage())
        {
            dataBuffer.ProcessMessage();
        }
    }
}

这个例子的控制流被大大简化了,但它应该能理解.我也没有提供 MyCustomDataBuffer 的实现,但是编写这样一个类并不太复杂;它实际上只是一个字节流.

The control flow of this example is greatly simplified, but it should get the idea across. I also don't provide an implementation for MyCustomDataBuffer, but writing such a class isn't too complicated; all it really is is a stream of bytes.

我们如何知道我们是否收到了完整的消息?嗯,这就是协议的重点:建立规则,让我们知道这些事情.让我们考虑一个简单的数据协议示例,其中每条消息由相同的两部分组成:

How do we know if we've received a complete message? Well, that's the point of a protocol: to establish the rules that allow us to know these things. Let's consider a simple example of a data protocol, where each message consists of the same two parts:

  • 2 个标头字节,表示消息的总大小(以字节为单位)
  • 构成消息字符串的任意字节数

有了这个协议,我们知道所有的消息至少有两个字节长(理论上最小的有效消息是00 02,它代表一个空字符串).我们还知道消息的前两个字节告诉我们消息的总大小,因此我们将知道何时停止读取数据.

With this protocol, we know that all messages are at least two bytes long (the theoretical smallest valid message is 00 02, which represents an empty string). We also know that the first two bytes of a message tell us the message's total size, so we'll know when to stop reading data.

因此,要实现上述代码中的 ContainsCompleteMessage() 方法,我们需要:

So, to implement the ContainsCompleteMessage() method from the code above, we need to:

  • 确保数据缓冲区中至少有 2 个字节;
  • 将这两个字节转换为整数;
  • 并确定我们的数据缓冲区中是否至少有那么多字节.

一旦我们知道我们有一个有效的消息——我们知道它有多大——我们所要做的就是从我们的数据缓冲区中切掉前 N 个字节(其中 N 是消息的大小),然后拉消息数据相关段外的消息字符串:

Once we know that we have a valid message -- and we know how big it is -- all we have to do is chop the first N bytes off of our data buffer (where N is the message's size), then pull the message string out of the relevant segment of the message data:

// here, 'msg' is a byte array that contains just the message data
var msgString = Encoding.UTF8.GetString(msg, 2, msg.Length - 2);
switch (msgString)
{
    case "kill": KillServer(); break;
    // etc. 
}

我在此描述的协议将满足您提出的通过网络发送短字符串的需求.概括它允许您发送更复杂的对象;您只需要添加额外的元数据来指定消息的布局.我把它留给读者作为练习.

The protocol I describe here will meet your stated need for sending short strings across the network. Generalizing it allows you to send more complicated objects; you just need to add additional metadata that specifies the layout of the message. I leave that as an exercise for the reader.

这篇关于简单的字符串消息客户端/服务器协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆