Shaw0xyz 发表于 2024-6-19 12:26:45

运用自定义协议设计与实现“跨网络计算器”

本帖最后由 Shaw0xyz 于 2024-6-20 13:46 编辑

1. 引言

在网络编程中,自定义协议可以用来实现特定的功能和需求。本文将介绍如何运用自定义协议设计和实现一个“跨网络计算器”,使得客户端可以通过网络向服务器发送计算请求,并接收结果。我们将从协议设计、服务器实现、客户端实现三个方面详细讲解,最终实现一个可以在局域网内进行简单加减乘除运算的计算器。

2. 协议设计

2.1 协议概述

我们设计的协议将包括请求和响应两个部分。客户端发送计算请求,服务器处理请求并返回结果。

2.2 请求格式

请求格式由操作符和操作数组成。每个请求包含一个操作符(+、-、*、/)和两个操作数,中间以空格分隔。例如:

+ 4 2

2.3 响应格式

响应格式为计算结果的字符串表示。例如,对于上述请求,响应可以是:

6

3. 服务器实现

服务器需要能够接收客户端的连接请求,解析计算请求,执行相应的计算,并返回结果。

3.1 创建TCP服务器

首先,我们创建一个TCP服务器来监听客户端的连接请求。

示例:

int port = 5000;
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
Console.WriteLine("Server started on port " + port);

3.2 接受并处理客户端连接

服务器接受客户端连接后,读取请求,解析并执行计算,然后返回结果。

示例:

while (true) {
    TcpClient client = listener.AcceptTcpClient();
    Thread clientThread = new Thread(() => HandleClient(client));
    clientThread.Start();
}

void HandleClient(TcpClient client) {
    NetworkStream stream = client.GetStream();
    byte[] buffer = new byte;
    int bytesRead;

    try {
      bytesRead = stream.Read(buffer, 0, buffer.Length);
      string request = Encoding.ASCII.GetString(buffer, 0, bytesRead);
      string response = ProcessRequest(request);
      byte[] responseBytes = Encoding.ASCII.GetBytes(response);
      stream.Write(responseBytes, 0, responseBytes.Length);
    } catch (Exception e) {
      Console.WriteLine("Error: " + e.Message);
    } finally {
      client.Close();
    }
}

3.3 处理请求

服务器需要解析请求并执行相应的计算。

示例:

string ProcessRequest(string request) {
    string[] parts = request.Split(' ');
    if (parts.Length != 3) {
      return "Error: Invalid request format";
    }

    string operation = parts;
    if (!double.TryParse(parts, out double operand1) || !double.TryParse(parts, out double operand2)) {
      return "Error: Invalid operands";
    }

    double result;
    switch (operation) {
      case "+":
            result = operand1 + operand2;
            break;
      case "-":
            result = operand1 - operand2;
            break;
      case "*":
            result = operand1 * operand2;
            break;
      case "/":
            if (operand2 == 0) return "Error: Division by zero";
            result = operand1 / operand2;
            break;
      default:
            return "Error: Invalid operation";
    }

    return result.ToString();
}

4. 客户端实现

客户端需要能够连接到服务器,发送计算请求,并接收和显示结果。

4.1 创建TCP客户端

客户端连接到服务器并发送计算请求。

示例:

string server = "127.0.0.1";
int port = 5000;
TcpClient client = new TcpClient(server, port);

4.2 发送请求

客户端发送计算请求并接收响应。

示例:

NetworkStream stream = client.GetStream();
byte[] requestBytes = Encoding.ASCII.GetBytes("+ 4 2");
stream.Write(requestBytes, 0, requestBytes.Length);

byte[] responseBytes = new byte;
int bytesRead = stream.Read(responseBytes, 0, responseBytes.Length);
string response = Encoding.ASCII.GetString(responseBytes, 0, bytesRead);

Console.WriteLine("Response: " + response);

client.Close();

5. 完整示例

以下是服务器和客户端的完整示例代码。

5.1 服务器代码

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

class Server {
    static void Main() {
      int port = 5000;
      TcpListener listener = new TcpListener(IPAddress.Any, port);
      listener.Start();
      Console.WriteLine("Server started on port " + port);

      while (true) {
            TcpClient client = listener.AcceptTcpClient();
            Thread clientThread = new Thread(() => HandleClient(client));
            clientThread.Start();
      }
    }

    static void HandleClient(TcpClient client) {
      NetworkStream stream = client.GetStream();
      byte[] buffer = new byte;
      int bytesRead;

      try {
            bytesRead = stream.Read(buffer, 0, buffer.Length);
            string request = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            string response = ProcessRequest(request);
            byte[] responseBytes = Encoding.ASCII.GetBytes(response);
            stream.Write(responseBytes, 0, responseBytes.Length);
      } catch (Exception e) {
            Console.WriteLine("Error: " + e.Message);
      } finally {
            client.Close();
      }
    }

    static string ProcessRequest(string request) {
      string[] parts = request.Split(' ');
      if (parts.Length != 3) {
            return "Error: Invalid request format";
      }

      string operation = parts;
      if (!double.TryParse(parts, out double operand1) || !double.TryParse(parts, out double operand2)) {
            return "Error: Invalid operands";
      }

      double result;
      switch (operation) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":
                result = operand1 * operand2;
                break;
            case "/":
                if (operand2 == 0) return "Error: Division by zero";
                result = operand1 / operand2;
                break;
            default:
                return "Error: Invalid operation";
      }

      return result.ToString();
    }
}

5.2 客户端代码

using System;
using System.Net.Sockets;
using System.Text;

class Client {
    static void Main() {
      string server = "127.0.0.1";
      int port = 5000;
      TcpClient client = new TcpClient(server, port);

      NetworkStream stream = client.GetStream();
      byte[] requestBytes = Encoding.ASCII.GetBytes("+ 4 2");
      stream.Write(requestBytes, 0, requestBytes.Length);

      byte[] responseBytes = new byte;
      int bytesRead = stream.Read(responseBytes, 0, responseBytes.Length);
      string response = Encoding.ASCII.GetString(responseBytes, 0, bytesRead);

      Console.WriteLine("Response: " + response);

      client.Close();
    }
}

6. 结论

本文介绍了如何设计和实现一个“跨网络计算器”。通过定义简单的请求和响应协议,使用C#实现了能够处理并发连接的TCP服务器,并展示了如何实现客户端与服务器之间的通信。希望本文能帮助开发者理解和掌握自定义协议的设计与实现,为实现更复杂的网络应用奠定基础。





/ 荔枝学姐de课后专栏 /

Hi!这里是荔枝学姐~

欢迎来到我的课后专栏

自然语言学渣 NLP摆烂姐

热衷于技术写作 IT边角料

AIGC & Coding & Linux ...

~互撩~ TG: @Shaw_0xyz
页: [1]
查看完整版本: 运用自定义协议设计与实现“跨网络计算器”