C++ TCP服务器的编写

头文件

#ifndef _TCP_H_
#define _TCP_H_

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

#endif

服务器

#include "TCP.h"

using namespace std;

class TCPServer {

public:
    // 构造函数,初始化端口号和套接字描述符
    TCPServer(int port) : port(port), server_fd(-1), client_fd(-1) {}

    // 析构函数,关闭服务器以释放资源
    ~TCPServer()
    {
        closeServer();
    }

    // 启动服务器,创建套接字并绑定和监听
    bool start() 
    {
        // 创建套接字,AF_INET 表示使用 IPv4 协议,SOCK_STREAM 表示使用 TCP
        server_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_fd == -1)
        {
            cerr << "创建套接字失败" << endl;
            return false;
        }

        // 配置服务器地址结构
        sockaddr_in server_addr{};
        server_addr.sin_family = AF_INET;            // 使用 IPv4
        server_addr.sin_addr.s_addr = INADDR_ANY;    // 允许任何地址连接
        server_addr.sin_port = htons(port);          // 端口号,使用网络字节序

        // 绑定套接字到指定端口
        if (bind(server_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0)
        {
            cerr << "绑定失败" << endl;
            close(server_fd);
            return false;
        }

        // 启动监听,最多允许 3 个连接请求等待队列
        if (listen(server_fd, 3) < 0)
        {
            cerr << "监听失败" << endl;
            close(server_fd);
            return false;
        }

        cout << "服务器正在监听" << port << endl;
        return true;
    }

    // 接收客户端连接
    bool acceptClient() 
        {
        sockaddr_in client_addr{};
        socklen_t client_len = sizeof(client_addr);

        // 接收客户端连接请求,阻塞等待直到有连接到达
        client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_len);
        if (client_fd < 0)
        {
            cerr << "连接失败" << endl;
            return false;
        }

        cout << "连接成功" << endl;
        return true;
    }

    // 接收客户端发送的数据
    string receiveData()
    {
        // 检查是否有客户端连接
        if (client_fd < 0)
        {
            cerr << "没有客户连接" << endl;
            return "";
        }

        char buffer[1024] = {0};  // 接收缓冲区
        ssize_t bytesReceived = recv(client_fd, buffer, sizeof(buffer), 0);  // 接收数据
        if (bytesReceived < 0)
        {
            cerr << "接收失败" << endl;
            return "";
        }

        // 将接收的数据转换为字符串并返回
        return string(buffer, bytesReceived);
    }

    // 向客户端发送数据
    void sendData(const string &data)
    {
        // 检查是否有客户端连接
        if (client_fd < 0)
        {
            cerr << "没有客户连接" << endl;
            return;
        }

        // 发送数据给客户端
        send(client_fd, data.c_str(), data.size(), 0);
    }

    // 关闭服务器和客户端连接
    void closeServer()
    {
        if (client_fd >= 0)
        {
            close(client_fd);  // 关闭客户端连接
            client_fd = -1;
        }
        if (server_fd >= 0)
        {
            close(server_fd);  // 关闭服务器套接字
            server_fd = -1;
        }
    }

private:
    int port;        // 服务器监听的端口号
    int server_fd;   // 服务器套接字文件描述符
    int client_fd;   // 客户端套接字文件描述符
};

// 主函数,测试 TCPServer 类的功能
int main()
{
    TCPServer server(8080);  // 创建一个监听 8080 端口的服务器

    // 启动服务器
    if (!server.start())
    {
        return -1;
    }

    // 等待客户端连接
    if (!server.acceptClient())
    {
        return -1;
    }

    // 接收客户端发送的信息
    string message = server.receiveData();
    cout << "收到: " << message << endl;

    // 向客户端发送一条消息
    server.sendData("你好 我是服务器");

    // 关闭服务器
    server.closeServer();

    return 0;
}

客户端

#include "TCP.h"

using namespace std;

// TCP 客户端类封装
class TCPClient {
public:
    // 构造函数,初始化服务器的 IP 地址和端口号
    TCPClient(const string &server_ip, int port) : server_ip(server_ip), port(port), sock_fd(-1) {}

    // 析构函数,关闭客户端连接以释放资源
    ~TCPClient()
    {
        closeConnection();
    }

    // 连接到服务器
    bool connectToServer()
    {
        // 创建套接字,AF_INET 表示使用 IPv4 协议,SOCK_STREAM 表示使用 TCP
        sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (sock_fd == -1)
        {
            cerr << "创建套接字失败" << endl;
            return false;
        }

        // 配置服务器地址结构
        sockaddr_in server_addr{};
        server_addr.sin_family = AF_INET;  // 使用 IPv4
        server_addr.sin_port = htons(port);  // 端口号,使用网络字节序

        // 将 IP 地址转换为网络字节序并存储
        if (inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr) <= 0)
        {
            cerr << "无效地址" << endl;
            close(sock_fd);
            return false;
        }

        // 连接服务器
        if (connect(sock_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0)
        {
            cerr << "连接失败" << endl;
            close(sock_fd);
            return false;
        }

        cout << "Connected to server" << endl;
        return true;
    }

    // 发送数据到服务器
    void sendData(const string &data)
    {
        if (sock_fd < 0)
        {
            cerr << "未建立连接" << endl;
            return;
        }

        // 发送数据到服务器
        send(sock_fd, data.c_str(), data.size(), 0);
    }

    // 从服务器接收数据
    string receiveData()
    {
        if (sock_fd < 0)
        {
            cerr << "未建立连接" << endl;
            return "";
        }

        char buffer[1024] = {0};  // 接收缓冲区
        ssize_t bytesReceived = recv(sock_fd, buffer, sizeof(buffer), 0);  // 接收数据
        if (bytesReceived < 0)
        {
            cerr << "接收失败" << endl;
            return "";
        }

        return string(buffer, bytesReceived);
    }

    // 关闭客户端连接
    void closeConnection()
    {
        if (sock_fd >= 0)
        {
            close(sock_fd);  // 关闭客户端连接
            sock_fd = -1;
        }
    }

private:
    string server_ip;  // 服务器的 IP 地址
    int port;               // 服务器的端口号
    int sock_fd;            // 客户端套接字文件描述符
};

// 主函数,测试 TCPClient 类的功能
int main()
    {
    TCPClient client("127.0.0.1", 8080);  // 创建一个连接到 127.0.0.1:8080 的客户端

    // 连接到服务器
    if (!client.connectToServer())
    {
        return -1;
    }

    // 向服务器发送一条消息
    client.sendData("你好 我是客户端");

    // 接收服务器的回应
    string message = client.receiveData();
    cout << "收到: " << message << endl;

    // 关闭客户端连接
    client.closeConnection();

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值