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

一、服务端

1.tcpServer.hpp

此文件负责实现一个tcp服务器

#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; // listen第二个参数
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)
    {
        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,面向字节流的,后续全部都是文件操作!
        serviceIO(sock);
        close(sock); // 要关闭使用完的sock,要不然会导致文件描述符泄露
    }
}

2.tcpServer.cpp

此文件负责tcp服务器的调用逻辑

#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]);

    unique_ptr<TcpServer> tsvr(new TcpServer(port));
    tsvr->initServer();
    tsvr->start();

    return 0;
}

二、客户端

1.tcpClient.hpp

此文件负责实现一个tcp客户端

#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.客户端不需要自己bind,让OS来bind
    // 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

此文件负责tcp客户端的调用逻辑

#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;
}

三、整体调用逻辑

1.双方调用逻辑

2.展示运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/915903.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

插入排序(sort)C++

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 时间限制&#xff1a;C/C/Rust/Pascal 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C/Rust/Pascal 512 M&#xff0c;其他语言1024 M 64bit IO Format: %lld 题目描述 插入排序是一种…

Vue2:脚手架 vue-cli

Vue2&#xff1a;脚手架 vue-cli 结构renderrefpropsmixinscoped 脚手架是Vue官方提供的Vue开发平台&#xff0c;.vue文件就需要通过脚手架来解析&#xff0c;所以对于单文件组件就依赖于脚手架。 安装&#xff1a; npm i -g vue/cli如果执行vue --version有输出&#xff0c;…

【MYSQL】主从复制机制(图解)

一、什么是主从复制 主从复制是一种通过binlog&#xff08;二进制日志&#xff09;进行操作的一直复制机制&#xff0c;它会有一个主数据库&#xff0c;还会有一个从数据库&#xff0c;根据binlog就可以把主数据库中的信息复制到从数据库之中。这个主从复制的好处就是如果在并发…

SpringCloud Gateway网关路由配置 接口统一 登录验证 权限校验 路由属性

介绍 Spring Cloud Gateway 根据请求的路径、HTTP 方法、头部等信息&#xff0c;将请求路由到对应的微服务实例。它支持基于动态路由规则的配置&#xff0c;可以根据请求的 URL、查询参数、请求头等条件&#xff0c;灵活地决定将请求转发到哪个微服务。Spring Cloud Gateway 提…

Java学习Day60:回家!(ElasticStatic)

1.what is ElasticStatic The Elastic Stack, 包括 Elasticsearch、 Kibana、 Beats 和 Logstash&#xff08;也称为 ELK Stack&#xff09;。能够安全可靠地获取任何来源、任何格式的数据&#xff0c;然后实时地对数据进行搜索、分析和可视化。 Elaticsearch&#xff0c;简称…

《进制转换:数字世界的奇妙变身术》

思维导图 一、什么是进制转换 在当今数字化飞速发展的时代&#xff0c;数字如同构建整个数字宇宙的基本粒子&#xff0c;无处不在且发挥着至关重要的作用。而在这个数字的魔法世界里&#xff0c;进制就像是不同的语言规则&#xff0c;每种进制都有着独特的构建方式和逻辑。 我…

Unity3D高级编程

1、标签(Tag)和图层(Layer) 他们都用于游戏物体分类&#xff0c;但是侧重点不一样。 标签便于代码中对特定物体进行操作。 图层则服务于渲染和碰撞管理&#xff0c;如控制摄像机渲染、光源影响及碰撞设置。 标签和图层的位置&#xff1a; &#xff08;1&#xff09;标签Tag…

Jmeter基础篇(22)服务器性能监测工具Nmon的使用

一、前言 我们在日常做压测的过程中&#xff0c;不仅仅需要监控TPS&#xff0c;响应时间&#xff0c;报错率等这些系统基础性能数据&#xff0c;还需要对服务器的性能&#xff08;如CPU、磁盘、内存、网络IO等&#xff09;做监控&#xff0c;以求对系统运行过程中的硬件性能有…

IDEA最新最全设置教程(包括常用的插件)

一、目的 统一安装一些必要的插件,方便大家开发。统一代码格式、注释格式、统一字符集编码。新加入的同事可以快速适应和熟悉,不需要在讲解IDEA配置问题。二、IDEA要修改的设置 新项目设置和设置 1. Java编译版本 这里请使用自己的JDK 2. 统一IDEA字符集 统一使用UTF-8 无…

日本IT工作好找吗?

在日本做IT是否好找工作&#xff0c;实际上取决于多个因素&#xff0c;包括个人的技术能力、日语水平、工作经验以及市场需求等。以下是对这一问题的详细分析&#xff1a; 技术能力与日语水平 技术能力&#xff1a;IT行业是一个技术密集型行业&#xff0c;技术能力自然是求职…

多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码

社团活动与组织 信息发布&#xff1a;系统支持社团发布活动信息、招募新成员等&#xff0c;方便社团进行线上线下活动的组织和管理。 增强凝聚力&#xff1a;通过系统&#xff0c;社团成员可以更好地交流和互动&#xff0c;增强社团的凝聚力和影响力。 生活服务功能 二手市场…

用 Python 从零开始创建神经网络(六):优化(Optimization)介绍

优化&#xff08;Optimization&#xff09;介绍 引言 引言 在随机初始化的模型中&#xff0c;或者即使是采用更复杂方法初始化的模型中&#xff0c;我们的目标是随着时间的推移培训或教育一个模型。为了训练一个模型&#xff0c;我们调整权重和偏差以提高模型的准确性和置信度…

架构篇(04理解架构的演进)

目录 学习前言 一、架构演进 1. 初始阶段的网站架构 2. 应用服务和数据服务分离 3. 使用缓存改善网站性能 4. 使用应用服务器集群改善网站的并发处理能力 5. 数据库读写分离 6. 使用反向代理和CDN加上网站相应 7. 使用分布式文件系统和分布式数据库系统 8. 使用NoSQL和…

Linux软件包管理与Vim编辑器使用指南

目录 一、Linux软件包管理器yum 1.什么是软件包&#xff1f; 2.什么是软件包管理器&#xff1f; 3.查看软件包 4.安装软件 ​编辑 5.卸载软件 Linux开发工具&#xff1a; 二、Linux编辑器---vim 1.vim的基本概念 (1) 正常/普通模式&#xff08;Normal mode&#xff0…

嵌入式硬件实战基础篇(一)-STM32+DAC0832 可调信号发生器-产生方波-三角波-正弦波

引言&#xff1a;本内容主要用作于学习巩固嵌入式硬件内容知识&#xff0c;用于想提升下述能力&#xff0c;针对学习STM32与DAC0832产生波形以及波形转换&#xff0c;对于硬件的降压和对于前面硬件篇的实际运用&#xff0c;针对仿真的使用&#xff0c;具体如下&#xff1a; 设…

怎么样绑定域名到AWS(亚马逊云)服务器

1&#xff0c;拿着你买的域名去亚马逊申请一个证书。申请证书分两种&#xff0c;一种是去亚马逊后台填域名手动申请 &#xff0c;另一种是通过API来申请&#xff0c;类似如下代码&#xff1a; 2、证验证书。有两种方式&#xff1a;一种是通过邮件&#xff0c;另一种去到域名提供…

【网络安全】公钥基础设施

1. PKI 定义 1.1 公钥基础设施的概念 公钥基础设施&#xff08;Public Key Infrastructure&#xff0c;简称PKI&#xff09;是一种基于公钥密码学的系统&#xff0c;它提供了一套完整的解决方案&#xff0c;用于管理和保护通过互联网传输的信息。PKI的核心功能包括密钥管理、…

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

一、服务端 1.udpServer.hpp 此文件负责实现一个udp服务器 #pragma once#include <iostream> #include <string> #include <cstdlib> #include <cstring> #include <functional> #include <strings.h> #include <unistd.h> #incl…

定时器简介

TIM(Timer定时器)简介 在第一部分,我们主要讲的是定时器基本定时的功能&#xff0c;也就是定一个时间&#xff0c;然后让定时器每隔这个时间产生一个中断&#xff0c;来实现每隔一个固定时间执行一段程序的目的&#xff0c;比如你要做个时钟、秒表&#xff0c;或者使用一些程序…

【论文阅读】HITS: High-coverage LLM-based Unit Test Generation via Method Slicing

HITS: High-coverage LLM-based Unit Test Generation via Method Slicing 1. 来源出处 本文是发表在2024年39th IEEE/ACM International Conference on Automated Software Engineering (ASE)上的论文。作者包括Zejun Wang, Kaiibo Liu, Ge Li和Zhi Jin,他们来自北京的PKU …