当前位置: 首页 > article >正文

【计算机网络】TCP网络程序

一、服务端

1.tcpServer.hpp

#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>

enum
{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    LISTEN_ERR
};

static const uint16_t gport = 8080;
static const int gbacklog = 5;
class TcpServer;

class ThreadData
{
public:
    ThreadData(TcpServer *self, int sock)
        : _self(self), _sock(sock)
    {}

public:
    TcpServer *_self;
    int _sock;
};

class TcpServer
{
public:
    // 构造函数
    TcpServer(const uint16_t &port = gport)
        : _listensock(-1), _port(port)
    {}
    // 析构函数
    ~TcpServer() {}
    // 初始化服务器
    void initServer()
    // 启动服务器
    void start()

private:
    int _listensock; // 不是用来进行数据通信的,他是用来监听链接到来,获取新链接的!
    uint16_t _port;  // 端口号
};

(1)initServer()

void initServer()
{
    // 1.创建socket文件套接字对象
    _listensock = socket(AF_INET, SOCK_STREAM, 0);
    if (_listensock < 0)
    {
        logMessage(FATAL, "create socket error");
        exit(SOCKET_ERR);
    }
    logMessage(NORMAL, "create socket success:%d", _listensock); // ? 后面可能会加东西

    // 2.bind绑定自己的网络信息
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(_port);
    local.sin_addr.s_addr = INADDR_ANY;
    if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        logMessage(FATAL, "bind socket error");
        exit(BIND_ERR);
    }
    logMessage(NORMAL, "bind socket success");

    // 3.设置socket 为监听状态
    if (listen(_listensock, gbacklog) < 0) // listen第二个参数以后在讲
    {
        logMessage(FATAL, "listen socket error");
        exit(LISTEN_ERR);
    }
    logMessage(NORMAL, "listen socket success");
}

(2)start()

void start()
{
    for (;;)
    {
        // 4.server 获取新链接
        // sock 才是和client进行通信的fd
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
        if (sock < 0)
        {
            logMessage(ERROR, "accept error, next");
            continue;
        }
        logMessage(NORMAL, "accept a new link success, get new sock:%d", sock);

        // 5.这里就是一个sock,未来通信我们就用这个sock,面向字节流的,后续全部都是文件操作!
        serviceIO(sock);
        close(sock); // 对一个已经使用完毕的sock,我们要关闭这个sock,要不然会导致,文件描述符泄露
    }
}

2.tcpServer.cpp

#include "tcpServer.hpp"
#include <memory>

using namespace std;

// 使用手册
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}

// ./tcpServer local_port
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    // tcp服务器的调用逻辑
    unique_ptr<TcpServer> tsvr(new TcpServer(port));
    tsvr->initServer();
    tsvr->start();

    return 0;
}

二、客户端

1.tcpClient.hpp

#pragma once

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

#define NUM 1024

class TcpClient
{
public:
    // 构造函数
    TcpClient(const std::string &serverip, const uint16_t &serverport)
    :_sock(-1), _serverip(serverip), _serverport(serverport)
    {}
    // 析构函数
    ~TcpClient()
    {
        if(_sock >= 0)
            close(_sock);
    }
    // 初始化客户端
    void initClient()
    // 启动客户端
    void start()

private:
    int _sock;
    std::string _serverip;
    uint16_t _serverport;
};

(1)initClient()

void initClient()
{
    // 1.创建socket
    _sock = socket(AF_INET, SOCK_STREAM, 0);
    if (_sock < 0)
    {
        std::cerr << "socket create error" << std::endl;
        exit(2);
    }

    // 2.tcp的客户端要不要bind?要的! 但是要不要显示的bind?不要!尤其这里client port要让OS自己随机指定!
    // 3.要不要listen?不要!
    // 4.要不要accept?不要!
}

(2)start()

void start()
{
    // 5.要发起连接!
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(_serverport);
    server.sin_addr.s_addr = inet_addr(_serverip.c_str());

    if (connect(_sock, (struct sockaddr *)&server, sizeof(server)) != 0)
    {
        std::cerr << "socket connet error" << std::endl;
    }
    else
    {
        // 成功连接
        std::string msg;
        while (true)
        {
            std::cout << "Enter# ";
            std::getline(std::cin, msg);
            write(_sock, msg.c_str(), msg.size());

            char buffer[NUM];
            int n = read(_sock, buffer, sizeof(buffer) - 1);
            if (n > 0)
            {
                // 目前我们可以吧读到的数据当成字符串
                buffer[n] = 0;
                std::cout << "Server回显# " << buffer << std::endl;
            }
            else
            {
                break;
            }
        }
    }
}

2.tcpClient.cpp

#include "tcpClient.hpp"
#include <memory>

// 使用手册
static void Usage(std::string proc)
{
    std::cout << "\nUsage:\n\t" << proc << " serverip serverport\n\n";
}

// ./tcpclient serverip serverport
int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    std::string serverip = argv[1];
    uint16_t serverport = atoi(argv[2]);

    std::unique_ptr<TcpClient> tcli(new TcpClient(serverip, serverport));
    tcli->initClient();
    tcli->start();

    return 0;
}


http://www.kler.cn/a/393506.html

相关文章:

  • 量化交易系统开发-实时行情自动化交易-3.4.2.2.Okex交易数据
  • 应用于新能源汽车NCV4275CDT50RKG车规级LDO线性电压调节器芯片
  • uniCloud云对象调用第三方接口,根据IP获取用户归属地的免费API接口,亲测可用
  • golang如何实现sse
  • DataWorks on EMR StarRocks,打造标准湖仓新范式
  • 普通电脑上安装属于自己的Llama 3 大模型和对话客户端
  • 【LLM学习笔记】第三篇:模型微调及LoRA介绍(附PyTorch实例)
  • 有什么好用的 WebSocket 调试工具吗?
  • Nuxt 版本 2 和 版本 3 的区别
  • LeetCode 216-组合总数Ⅲ
  • 【Qualcomm】Ubuntu20.04安装QualcommPackageManager3
  • HTML 基础架构:理解网页的骨架
  • 【Git】Git Clone 指定自定义文件夹名称:详尽指南
  • 多态之魂:C++中的优雅与力量
  • Leetcode 最后一个单词的长度
  • Clickhouse集群新建用户、授权以及remote权限问题
  • 怎么用家用电脑做服务器(web服务器、ftp服务器、小程序服务器,云电脑)
  • sql专题 之 三大范式
  • 标准C++ 字符串
  • 操作系统lab3-进程同步实验
  • uniapp使用scroll-view下拉刷新与上滑加载
  • idea正则表达式-正则替换示例-2024.11笔记
  • 2024中国游戏出海情况
  • attention 注意力机制 学习笔记-GPT2
  • python---基础语法
  • 【HarmonyOS】Install Failed: error: failed to install bundle.code:9568289