linux下tcp/ip网络通信笔记1,

news2025/7/9 5:11:03

本文章主要为博主在学习网络通信的笔记+一个Udp_echo_server,和client的代码实现

1,网络发展,网络协议,意识到网络通信——不同主机的进程间通信,

2,学习如何在应用层调用系统提供的接口进行通信,echo_Udp_server, Udp_client,

目录

一,学的时候找别人的资源过一遍这些概念就好 

二,贴点代码,

InetAddr.hpp

common.hpp

Server.hpp

Server_main.cpp

Client_main.hpp

makefile



一,学的时候找别人的资源过一遍这些概念就好 

                以下个人理解,未必和发展历史相关,因果正确,博主建议概念性的知识你找别人看,博主的笔记仅仅为了给自己后期复习提醒一下,有些抽象和忽略,

发展/背景:局域网->广域网,主机数量变多,距离变远,各个要连接起来的局域网的协议不同,但却要组织起来进行通信,所以再次分层/包装->网络层,

下面列些概念性的,懒得往这里搬了,

1,纵向分层,横向模块

2,port端口号——主机在网络通信这块儿区别进程的标识符,

      Ip地址——主机在网络里的标识符,

      Mac地址——主机在局域网的标识符,

3,

      

 ​​​​​​​​​​​​​​

二,贴点代码,

博主在写的时候遇见最大的坑是ip转了两次(一次点分十进制转网络(inet_pton函数)一次在自己包装的inetaddr里也处理了一次(htonl函数)),导致出错, ,用到的系统调用的函数较少,代码量少,就这样了,跨过了/写过了,就觉得这echo_server和client也就那样,

InetAddr.hpp
#pragma once
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "common.hpp"
// 就把这个class当包装好的sockaddr_in用
// 主要是ip,port 本地转网络填socket, 网络转本地已经转好
class InetAddr{
private:
    void PortNet2Host(){ _port = ntohs(_addr.sin_port); }
    void IpNet2Host(){ 
        char buf[64] = { 0 };
        const char* ip = inet_ntop(AF_INET, &_addr.sin_addr.s_addr, buf, sizeof(buf));
        _ip = ip; 
    }
public:
    InetAddr(){
        memset(&_addr, 0, sizeof(_addr));
    }
    InetAddr(struct sockaddr_in& addr)
    {   
        memset(&_addr, 0, sizeof(_addr));
        _addr.sin_family = addr.sin_family;
        _addr.sin_addr.s_addr = addr.sin_addr.s_addr;
        _addr.sin_port = addr.sin_port;

        Init();
    }
    InetAddr(uint32_t ip, uint16_t port)
    {
        // ip = htonl(ip);
        port = htons(port);

        memset(&_addr, 0, sizeof(_addr));
        _addr.sin_family = AF_INET;
        _addr.sin_addr.s_addr = ip;
        _addr.sin_port = port;
        // 由_addr去设置_ip和_port

        Init();
    }
    InetAddr(uint16_t port){
        port = htons(port);

        memset(&_addr, 0, sizeof(_addr));
        _addr.sin_family = AF_INET;
        _addr.sin_addr.s_addr = INADDR_ANY;
        _addr.sin_port = port;

        Init();
    }
    void Init(){
        PortNet2Host();
        IpNet2Host();
    }
    struct sockaddr* Sockaddr_in(){ return CONV(&_addr); }
    socklen_t Socklen() { return sizeof(_addr); }
    std::string Ip(){ return _ip; }
    uint16_t Port(){ return _port; }
    ~InetAddr(){

    }

private:
    struct sockaddr_in _addr;
    std::string _ip = "";
    uint16_t _port = 0;
};
common.hpp
#pragma once

#include <iostream>


#define Die(code)   \
    do              \
    {               \
        exit(code); \
    } while (0)

#define CONV(v) (struct sockaddr *)(v)

enum 
{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    RECVFORM_ERR,
    SENDTO_ERR
};
Server.hpp
#pragma once
#include <iostream>
#include <functional>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "InetAddr.hpp"
#include "common.hpp"
// ipv4 Udp EchoServer

// 服务器需要,自己设置的port,ip写INADDR_ANY,
// 1 socket, 
// 2 bind
// 3 调用recvfrom()与sendto()开始通信
// 我需要设计一个class server, 给它指定的port,它能自己socket并bind, 要有start函数去使用recvfrom,sendto去通信
// 我还要一个class, 给它sockaddr_in, 它让我直接看到ip的点分十进制, 给它port, ip = INADDR_ANY,能吐出sockaddr_in.

// server class == 一个运行的server, 
using func_t = std::function<std::string(const std::string&)>;
#define INIT_PORT 8080


class UdpServer{
public:
    UdpServer(uint16_t port = INIT_PORT, func_t func = [](const std::string& s1){
        return s1;
    })
    :_addr(INADDR_ANY, port)
    {
        _func = func;
    }
    void Init(){
        // 建文件描述符
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if(_sockfd < 0){
            Die(SOCKET_ERR);
        }
        if(bind(_sockfd, _addr.Sockaddr_in(), _addr.Socklen())){
            Die(BIND_ERR);
        }
    }
    void start(){
        _isrunning = true;
        std::cout << "start_server ~\n" << "wait client send messsge!" << std::endl;

        while(1){
            InetAddr client_sockaddr;
            char buf[1024] = { 0 };
            socklen_t size = client_sockaddr.Socklen();
            int n = recvfrom(_sockfd, buf, sizeof(buf) - 1, 0, client_sockaddr.Sockaddr_in(), &size);
            if(n < 0){
                Die(RECVFORM_ERR);
            }

            std::string s(buf);
            client_sockaddr.Init();
            std::cout << client_sockaddr.Ip() << ":" << client_sockaddr.Port() << ": " << s << std::endl;
            // s = _func(s);
            //
            n = sendto(_sockfd, s.c_str(), s.size(), 0, client_sockaddr.Sockaddr_in(), client_sockaddr.Socklen());
            if(n < 0){
                Die(SENDTO_ERR);
            }
        }
        _isrunning = false;
    }
private:
    int _sockfd = -1;
    InetAddr _addr; // 只存个自己的socket
    bool _isrunning = false; // 服务器运行状态

    // 业务
    func_t _func;
};
Server_main.cpp
#include "Server.hpp"
#include <functional>
#include <memory>
int main(int argc, char* argv[]){
    if(argc != 2){
        std::cout << "die~\n";
        Die(-1);
    }
    uint16_t port = atoi(argv[1]);
    
    std::unique_ptr<UdpServer> svr_uptr = std::make_unique<UdpServer>(port);
    svr_uptr->Init();
    std::cout << "Init_server ~\n";
    svr_uptr->start();
    return 0;
}
Client_main.hpp

#include <iostream>

#include "common.hpp"
#include "InetAddr.hpp"

int main(int argc, char* argv[]){
    if(argc != 3){
        exit(-1);
    }
    uint32_t ip = 0;
    inet_pton(AF_INET, argv[1], &ip);
    uint16_t port = atoi(argv[2]);
    InetAddr aim_server_addr(ip, port);
    int _fd = socket(AF_INET, SOCK_DGRAM, 0);
    while(1){
        std::cout << "Please Enter# " << std::endl;
        std::string s;
        socklen_t size = aim_server_addr.Socklen();
        std::getline(std::cin, s);
        int n = sendto(_fd, s.c_str(), s.size(), 0, aim_server_addr.Sockaddr_in(), aim_server_addr.Socklen());
        if(n < 0){
            Die(SENDTO_ERR);
        }
        std::cout << "sendto ed" << std::endl;
        std::cout << "sendto ed" << std::endl;
        std::cout << "sendto ed" << std::endl;
        std::cout << "sendto ed" << std::endl;
        std::cout << "sendto ed" << std::endl;
        std::cout << "sendto ed" << std::endl;
        
        char buf[1024] = { 0 }; 
        n = recvfrom(_fd, buf, sizeof(buf) - 1, 0, aim_server_addr.Sockaddr_in(), &size);
        if(n > 0){
            buf[n] = 0;
            std::cout << buf << std::endl;
        }
    }
    return 0;
}
makefile
.PHONY:all
all:server_udp client_udp

server_udp:Server_main.cpp
	g++ -o $@ $^ -std=c++17
client_udp:Client_main.cpp
	g++ -o $@ $^ -std=c++17

.PHONY:clean
clean:
	rm -f server_udp client_udp

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

语音识别——声纹识别

通过将说话人的声音与数据库中的记录声音进行比对&#xff0c;判断说话人是否为数据库白名单中的同一人&#xff0c;从而完成语音验证。目前&#xff0c;3D-Speaker 声纹验证的效果较为出色。 3D-Speaker 是一个开源工具包&#xff0c;可用于单模态和多模态的说话人验证、说话…

window 显示驱动开发-报告图形内存(三)

图形内存报告示例 示例 1&#xff1a;笔记本电脑上的 128 MB 专用板载图形内存 以下屏幕截图显示了使用 Intel Iris 离散图形适配器运行 Windows 11 的 Surface 笔记本电脑的计算图形内存数。 适配器的可用内存总数为 16424 MB&#xff0c;用于图形用途&#xff0c;细分如下&…

UE5 GAS框架解析内部数据处理机制——服务器与客户端

当&#xff0c; gas通过点击鼠标光标触发事件时&#xff0c;内部的处理机制。 当通过点击事件&#xff0c;命中中目标时&#xff0c; 可获取到对应的TargetData 目标数据。处理相应的操作。 仅有本地的客户端的情况下。命中并不会有什么异常。 当存在服务器时&#xff0c; 服…

开源GPU架构RISC-V VCIX的深度学习潜力测试:从RTL仿真到MNIST实战

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生专属优惠。 一、开篇&#xff1a;AI芯片架构演变的三重挑战 &#xff08;引述TPUv4采用RISC-V的行业案…

Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(七)

Android Coli 3 ImageView load two suit Bitmap thumb and formal&#xff0c;Kotlin&#xff08;七&#xff09; 在 Android Coli 3 ImageView load two suit Bitmap thumb and formal&#xff0c;Kotlin&#xff08;六&#xff09;-CSDN博客 的基础上改进&#xff0c;主要是…

【工具】Windows|外接的显示器怎么用软件调亮度(Brightness Slider)

文章目录 工具安装及使用Twinkle Tray&#xff1a;Brightness Slider补充背景知识1. DDC/CI&#xff08;Display Data Channel Command Interface&#xff09;2. WMI&#xff08;Windows Management Instrumentation&#xff09;3. Twinkle Tray如何结合两者&#xff1f;对比总…

【Nextcloud】使用 LNMP 架构搭建私有云存储:Nextcloud 实战指南

目录 一、环境准备与基础配置 1. 系统环境要求 2. 初始化系统配置 二、搭建 LNMP 基础架构 1. 一键安装 LNMP 组件 2. 启动数据库服务 三、部署 Nextcloud 存储服务 1. 上传并解压安装包 2. 设置目录权限&#xff08;测试环境配置&#xff09; 3. 配置 MariaDB 数据库…

【办公类-100-01】20250515手机导出教学照片,自动上传csdn+最小化Vscode界面

背景说明&#xff1a; 每次把教学照片上传csdn&#xff0c;都需要打开相册&#xff0c;一张张截图&#xff0c;然后ctrlV黏贴到CSDN内&#xff0c;我觉得太烦了。 改进思路&#xff1a; 是否可以先把所有照片都上传到csdn&#xff0c;然后再一张张的截图&#xff08;去掉幼儿…

uniapp-商城-60-后台 新增商品(属性的选中和页面显示,数组join 的使用)

前面添加了属性&#xff0c;添加属性的子级项目。也分析了如何回显&#xff0c;但是在添加新的商品的时&#xff0c;我们也同样需要进行选择&#xff0c;还要能正常的显示在界面上。下面对页面的显示进行分析。 1、界面情况回顾 属性显示其实是个一嵌套的数据显示。 2、选中的…

[c语言日寄]数据结构:栈

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

WEB安全--Java安全--LazyMap_CC1利用链

一、前言 该篇是基于WEB安全--Java安全--CC1利用链-CSDN博客的补充&#xff0c;上篇文章利用的是TransformedMap类&#xff0c;而CC链的原作者是利用的LazyMap类作为介质进行的触发。 所以本文将分析国外原作者在ysoserial commonscollections1中给出的CC1利用链。 二、回顾梳…

黑马k8s(六)

1.Deployment&#xff08;Pod控制器&#xff09; Selector runnginx 标签选择&#xff1a;会找pod打的标签 执行删除之后&#xff0c;pod也会删除&#xff0c;Terminating正在删除 如果想要访问其中的一个pod借助&#xff1a;IP地址端口号访问 假设在某一个瞬间&#xff0c;…

【OpenGL学习】(一)创建窗口

文章目录 【OpenGL学习】&#xff08;一&#xff09;创建窗口 【OpenGL学习】&#xff08;一&#xff09;创建窗口 GLFW OpenGL 本身只是一套图形渲染 API&#xff0c;不提供窗口创建、上下文管理或输入处理的功能。 GLFW 是一个支持创建窗口、处理键盘鼠标输入和管理 OpenGL…

AI大语言模型评测体系演进与未来展望

随着人工智能技术的飞速发展,大语言模型(LLMs)已成为自然语言处理领域的核心研究方向。2025年最新行业报告显示,当前主流模型的评测体系已从单一任务评估转向多维度、全链路的能力剖析。例如,《全球首个大语言模型意识水平”识商”白盒DIKWP测评报告》通过数据、信息、知识…

微服务项目->在线oj系统(Java版 - 5)

相信自己,终会成功 微服务代码: lyyy-oj: 微服务 目录 C端代码 用户题目接口 修改后用户提交代码(应用版) 用户提交题目判题结果 代码沙箱 1. 代码沙箱的核心功能 2. 常见的代码沙箱实现方式 3. 代码沙箱的关键问题与解决方案 4. 你的代码如何与沙箱交互&#xff1f; …

get请求使用数组进行传参

get请求使用数组进行传参,无需添加中括号 mvc接口要添加参数名&#xff0c;使用array承接。不能用list, 否则会报错 这里是用apifox模拟前端调用。 前端调用代码 // 根据项目ID和角色ID查询相关审批人 export function findRelativeApproverByProjectIdAndRoleId(roleIds, p…

【MySQL成神之路】MySQL常用语法总结

目录 MySQL 语法总结 数据库操作 表操作 数据操作 查询语句 索引操作 约束 事务控制 视图操作 存储过程和函数 触发器 用户和权限管理 数据库操作 创建数据库&#xff1a; CREATE DATABASE database_name; 选择数据库&#xff1a; USE database_name; 删除数…

Linux动静态库制作与原理

什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作系统…

ffmpeg 把一个视频复制3次

1. 起因&#xff0c; 目的: 前面我写过&#xff0c;使用 python 把一个视频复制3次但是速度太慢了&#xff0c;我想试试看能否改进。而且我想换一种新的视频处理思路&#xff0c;并试试看速度如何。 2. 先看效果 效果就是能行&#xff0c;而且速度也快。 3. 过程: 代码 1…

GPT/Claude3国内免费镜像站更新 亲测可用

无限次使用&#xff1a;无限制的提问次数&#xff0c;不设上限&#xff0c;随心所欲。 无需魔法、稳定流畅&#xff1a;操作简便&#xff0c;无需复杂设置&#xff0c;即可享受稳定流畅的服务。 手机和电脑均能用&#xff1a;轻松适配手机和电脑&#xff0c;使用体验更佳。 …