云计算百科
云计算领域专业知识百科平台

使用C++实现简单的TCP服务器和客户端

使用C++实现简单的TCP服务器和客户端

  • 介绍
  • 准备工作
  • 1. TCP服务器实现
    • 代码结构
    • 解释
  • 2. TCP客户端实现
    • 代码结构
    • 解释
  • 3. 测试
    • 1.编译:
    • 2.运行
  • 结语

介绍

本文将通过一个简单的例子,介绍如何使用C++实现一个基本的TCP服务器和客户端。这个例子展示了如何创建服务器端接收客户端的连接,如何处理接收到的数据,并如何将数据发送回客户端。

我们会分两部分来介绍:

  • TCP服务器的实现:包括如何创建服务器、监听端口、接收客户端请求等。
  • TCP客户端的实现:客户端如何连接到服务器、发送数据并接收服务器返回的数据。
  • 准备工作

    首先,确保你的开发环境中已经安装了C++编译器(如GCC或Clang)以及支持的标准库。在Linux或类Unix系统上进行开发是最常见的,下面的代码也适用于这种环境。

    1. TCP服务器实现

    代码结构

    首先,来看下TCP服务器的代码实现:

    #include <arpa/inet.h>
    #include <cstring>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <iostream>
    #include <thread>

    #define SERVER_PORT 12345
    #define BUFFER_SIZE 1024

    class TcpServer {
    public:
    TcpServer(int port);
    ~TcpServer();
    void Start();
    void Stop();

    private:
    void ListenThreadFunc();
    void ReceiveThreadFunc(int clientSocket);
    void CloseListenSocket();
    void CloseDataSocket();

    int mListenSocket;
    int mDataSocket;
    int mPort;
    std::unique_ptr<std::thread> mListenThread;
    bool mRunning;
    };

    TcpServer::TcpServer(int port) : mListenSocket(1), mDataSocket(1), mPort(port), mListenThread(nullptr), mRunning(false) {}

    TcpServer::~TcpServer() {
    Stop();
    }

    void TcpServer::Start() {
    if (mRunning) {
    std::cerr << "Server is already running!" << std::endl;
    return;
    }

    mRunning = true;

    mListenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (mListenSocket == 1) {
    std::cerr << "Failed to create listen socket!" << std::endl;
    return;
    }

    sockaddr_in serverAddr{};
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(mPort);
    serverAddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(mListenSocket, reinterpret_cast<const sockaddr*>(&serverAddr), sizeof(serverAddr)) == 1) {
    std::cerr << "Failed to bind socket!" << std::endl;
    CloseListenSocket();
    return;
    }

    if (listen(mListenSocket, 5) == 1) {
    std::cerr << "Failed to listen on socket!" << std::endl;
    CloseListenSocket();
    return;
    }

    mListenThread = std::make_unique<std::thread>([this] { ListenThreadFunc(); });
    }

    void TcpServer::Stop() {
    if (!mRunning) return;

    mRunning = false;
    CloseListenSocket();
    CloseDataSocket();

    if (mListenThread && mListenThread->joinable()) {
    mListenThread->join();
    }
    }

    void TcpServer::ListenThreadFunc() {
    while (mRunning) {
    sockaddr_in clientAddr{};
    socklen_t len = sizeof(clientAddr);

    int clientSocket = accept(mListenSocket, reinterpret_cast<sockaddr*>(&clientAddr), &len);
    if (clientSocket == 1) {
    std::cerr << "Accept failed!" << std::endl;
    continue;
    }

    std::cout << "Client connected!" << std::endl;

    std::thread receiveThread([this, clientSocket] { ReceiveThreadFunc(clientSocket); });
    receiveThread.detach();
    }
    }

    void TcpServer::ReceiveThreadFunc(int clientSocket) {
    char buffer[BUFFER_SIZE];
    while (mRunning) {
    memset(buffer, 0, BUFFER_SIZE);
    int res = recv(clientSocket, buffer, sizeof(buffer) 1, 0);
    if (res <= 0) {
    std::cerr << "Receive failed or client disconnected!" << std::endl;
    break;
    }

    std::cout << "Received from client: " << buffer << std::endl;
    send(clientSocket, "Message received", 17, 0); // Send acknowledgment back
    }

    CloseDataSocket();
    }

    void TcpServer::CloseListenSocket() {
    if (mListenSocket != 1) {
    close(mListenSocket);
    mListenSocket = 1;
    }
    }

    void TcpServer::CloseDataSocket() {
    if (mDataSocket != 1) {
    close(mDataSocket);
    mDataSocket = 1;
    }
    }

    int main() {
    TcpServer server(SERVER_PORT);
    server.Start();

    std::this_thread::sleep_for(std::chrono::minutes(10)); // Server will run for 10 minutes
    server.Stop();

    return 0;
    }

    解释

    • TcpServer 类:定义了一个 TcpServer 类来处理服务器的启动、停止以及接收客户端请求。
    • Start() 方法:创建一个监听套接字,绑定端口并开始监听。
    • ListenThreadFunc() 方法:负责监听来自客户端的连接请求。
    • ReceiveThreadFunc() 方法:每个客户端连接都会创建一个新的线程来处理数据接收。

    2. TCP客户端实现

    代码结构

    接下来是客户端的实现。客户端需要连接到服务器,发送请求并接收响应。

    #include <iostream>
    #include <string>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <cstring>
    #include <sys/socket.h>

    #define SERVER_PORT 12345
    #define SERVER_IP "127.0.0.1"
    #define BUFFER_SIZE 1024

    int main() {
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == 1) {
    std::cerr << "Create socket failed!" << std::endl;
    return 1;
    }

    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVER_PORT);
    serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);

    if (connect(clientSocket, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr)) == 1) {
    std::cerr << "Connect to server failed!" << std::endl;
    close(clientSocket);
    return 1;
    }

    std::cout << "Connected to server!" << std::endl;

    // Send message
    std::string message = "Hello from client!";
    send(clientSocket, message.c_str(), message.size(), 0);

    // Receive response
    char buffer[BUFFER_SIZE];
    ssize_t receivedBytes = recv(clientSocket, buffer, sizeof(buffer) 1, 0);
    if (receivedBytes == 1) {
    std::cerr << "Receive failed!" << std::endl;
    } else if (receivedBytes == 0) {
    std::cerr << "Server closed connection!" << std::endl;
    } else {
    buffer[receivedBytes] = '\\0';
    std::cout << "Received from server: " << buffer << std::endl;
    }

    close(clientSocket);
    return 0;
    }

    解释

    • TcpClient:客户端通过 connect() 与服务器建立连接,使用 send() 发送数据,并通过 recv() 接收服务器的响应。

    3. 测试

    1.编译:

    • 编译服务器:

    g++ TcpServer.cpp -o TcpServer -std=c++17 -lpthread

    • 编译客户端

    g++ TcpClient.cpp -o TcpClient -std=c++17

    2.运行

    • 启动服务器:

    ./TcpServer

    • 启动客户端

    ./TcpClient

    结语

    通过这篇文章,我们实现了一个简单的 TCP 服务器和客户端示例,学习了如何使用 C++ 来进行网络编程。在实际项目中,你可以根据需求进一步扩展这些功能,比如加入多线程处理、客户端消息队列、认证机制等。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 使用C++实现简单的TCP服务器和客户端
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!