Linux 网络编程 + 笔记

协议:一组规则

分层模型结构:

  • OSI七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
  • TCP/IP 4层模型:链路层/网络接口层、网络层、传输层、应用层
    • 应用层:http、ftp、nfs、ssh、telnet、
    • 传输层:TCP、UDP
    • 网络层:IP、ICMP、IGMP
    • 链路层:以太网帧协议、ARP

C/S模型和B/S模型

  • C/S模型:client-server
  • B/S模型:browser-server

网络传输流程:

  • 数据没有封装之前,是不能在网络中传递
  • 数据-》应用层-》传输层-》网络层-》链路层  --- 网络环境

以太网帧协议:

  • ARP协议:根据IP地址获取mac地址
  • 以太网帧协议:根据mac地址,完成数据包传输

IP协议:

  • 版本: IPv4、IPv6  -- 4位
  • TTL:time to live (设置数据包在路由节点中的跳转上限,每经过一个路由节点,该值-1, 减为0的路由,有义务将该数据包丢弃)
  • 源IP:32位 -- 4字节 
192.168.1.108 --- 点分十进制 IP地址(string)
  • 目的IP:32位--- 4字节

IP地址:可以在网络环境中,唯一标识一台主机

端口号:可以进行网络通信的一台主机上,唯一标识一个进程

IP地址+端口号:可以在网络环境中,唯一标识一个进程

UDP协议

    16位:源端口号     2^16 = 65536
    
    16位:目的端口号

TCP协议

    16位:源端口号     2^16 = 65536

    16位:目的端口号
    
    32序号
    
    32确认序号
    
    6个标志位

    16位窗口大小       2^16 = 65536

网络套接字:socket

  • 一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现)
  • 在通信过程中,套接字一定是成对出现的

网络字节序:

  • 小端法:(pc本地存储)    高位存高地址,低位存低地址            int a = 0x12345678
  • 大端法:(网络存储)        高位存低地址,低位存高地址         
    htonl --> 本地--》网络 (IP)			192.168.1.11 --> string --> atoi --> int --> htonl --> 网络字节序

	htons --> 本地--》网络 (port)

	ntohl --> 网络--》 本地(IP)

	ntohs --> 网络--》 本地(Port)

 注意:htonl --> 本地 --> 网络(IP)

192.168.1.11 --> string --> atoi --> int --> htonl --> 网络字节序

IP地址转换函数

  1. inet_pton
  2. inet_ntop
  • 本地字节序(string IP) ---> 网络字节序 
// 本地字节序(string IP) ---> 网络字节序
int inet_pton(int af, const char *src, void *dst);
    af: AF_INET,AF_INET6
    src:传入,IP地址(点分十进制)
    dst:传出转换后的 网络字节序的 IP地址
    返回值:
	    成功:   1
	    异常:   0,说明src指向的不是一个有效的ip地址
		失败:  -1
NAME
       inet_pton - convert IPv4 and IPv6 addresses from text to binary form

SYNOPSIS
       #include <arpa/inet.h>

       int inet_pton(int af, const char *src, void *dst);

DESCRIPTION
       This  function converts the character string src into a network address
       structure in the af address family, then  copies  the  network  address
       structure  to dst.  The af argument must be either AF_INET or AF_INET6.
       dst is written in network byte order.
  • 网络字节序  ---> 本地字节序(string IP) 
// 网络字节序  ---> 本地字节序(string IP)
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
    af: AF_INET,AF_INET6
    src: 网络字节序IP地址
    dst: 本地字节序(string IP)
    size: dst的大小
    返回值: 
        成功: dst
        失败: NULL
NAME
       inet_ntop - convert IPv4 and IPv6 addresses from binary to text form

SYNOPSIS
       #include <arpa/inet.h>

       const char *inet_ntop(int af, const void *src,
                             char *dst, socklen_t size);

DESCRIPTION
       This  function  converts  the  network  address  structure src in the af
       address family into a character string.  The resulting string is  copied
       to  the buffer pointed to by dst, which must be a non-null pointer.  The
       caller specifies the number of bytes available in  this  buffer  in  the
       argument size.
  • sockaddr地址结构: IP + Port  --> 在网络环境中唯一标识一个进程 
sockaddr地址结构: IP + Port  --> 在网络环境中唯一标识一个进程
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
#if 0
    int dst;
    inet_pton(AF_INET,"192.168.1.100",(void*)dst);   
    addr.sin_addr.s_addr = dst;
#else
    // 取出系统中有效的任意IP地址(二进制类型)
    addr.sin_addr.s_addr =  htonl(INADDR_ANY);
    bind(fd,(struct sockaddr*)&addr,sizeof(addr));

  • socket函数,创建一个套接字
socket函数
    #include <sys/socket.h>
    // 创建一个套接字
    int socket(int domain, int type, int protocol);
    domain: AF_INET,AF_INET6
    type: SOCK_STREAM,SOCK_DGRAM
    protocol: 0
    返回值:
        成功: 新套接字所对应文件描述符
        失败: -1 errno
NAME
       socket - create an endpoint for communication

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);

DESCRIPTION
       socket()  creates  an  endpoint  for  communication  and  returns a file
       descriptor that refers to that endpoint.  The file  descriptor  returned
       by  a  successful  call  will be the lowest-numbered file descriptor not
       currently open for the process.
  • bind函数 
#include <arpa/inet.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    sockfd: socket 函数返回值
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    addr:传入参数(struct sockaddr*)&addr
    addrlen:sizeof(addr) 地址结构的大小
    返回值:
        成功: 0
        失败: -1 errno
NAME
       bind - bind a name to a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);

DESCRIPTION
       When  a  socket  is  created  with  socket(2), it exists in a name space
       (address family) but has no address assigned to it.  bind() assigns  the
       address specified by addr to the socket referred to by the file descrip‐
       tor sockfd.  addrlen specifies the size, in bytes, of the address struc‐
       ture  pointed  to  by  addr.   Traditionally,  this  operation is called
       “assigning a name to a socket”.

       It is normally necessary to assign a local address using bind() before a
       SOCK_STREAM socket may receive connections (see accept(2)).
  • listen函数,设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)
// 设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)
int listen(int sockfd, int backlog);
    sockfd: socket 函数返回值
    backlog: 上限数值,最大值为128
    返回值:
        成功: 0
        失败: -1 errno
NAME
       listen - listen for connections on a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int listen(int sockfd, int backlog);

DESCRIPTION
       listen()  marks  the  socket  referred to by sockfd as a passive socket,
       that is, as a socket that will be used  to  accept  incoming  connection
       requests using accept(2).

       The sockfd argument is a file descriptor that refers to a socket of type
       SOCK_STREAM or SOCK_SEQPACKET.

       The backlog argument defines the maximum length to which  the  queue  of
       pending  connections  for  sockfd  may  grow.   If  a connection request
       arrives when the queue is full, the client may receive an error with  an
       indication  of  ECONNREFUSED  or,  if  the  underlying protocol supports
       retransmission, the request may be ignored so that a later reattempt  at
       connection succeeds.
  • accept函数,阻塞等待客户端建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符
// 阻塞等待客户端建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    sockfd:socket 函数返回值
    addr:传出参数,成功与服务器建立连接的那个客户端的地址结构(IP+port)
        socklen_t client_addr_len = sizeof(addr);
        addrlen:传入传出  &client_addr_len
                 入:addr的大小  
                 出:客户端addr实际大小
        返回值:
            成功:能与客户端进行数据通信的 socket 对应的文件描述
            失败:-1,errno
NAME
       accept, accept4 - accept a connection on a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <sys/socket.h>

       int accept4(int sockfd, struct sockaddr *addr,
                   socklen_t *addrlen, int flags);

DESCRIPTION
       The  accept()  system  call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET).  It extracts
       the first connection request on the queue of pending connections for the listening socket, sockfd, creates  a  new
       connected  socket, and returns a new file descriptor referring to that socket.  The newly created socket is not in
       the listening state.  The original socket sockfd is unaffected by this call.
  • connect函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    sockfd: socket 函数返回值

    struct sockaddr_in server_addr; // 服务器地址结构
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);// 跟服务器bind时设定的 port 完全一致。
    inet_pton(AF_INET, "服务器IP地址", &server_addr.sin_addr.s_addr);

    addr:传入参数,服务器的地址结构
    addrlen:服务器的地址结构的大小

    返回值:
        成功: 0
        失败: -1,errno

    如果不使用bind绑定客户端地址结构,采用"隐式绑定".
NAME
       connect - initiate a connection on a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);

DESCRIPTION
       The  connect()  system  call connects the socket referred to by the file
       descriptor sockfd to the address specified by addr.  The  addrlen  argu‐
       ment  specifies  the size of addr.  The format of the address in addr is
       determined by the address space of the socket sockfd; see socket(2)  for
       further details.

       If  the socket sockfd is of type SOCK_DGRAM, then addr is the address to
       which datagrams are sent by default, and the  only  address  from  which
       datagrams  are  received.   If  the  socket  is  of  type SOCK_STREAM or
       SOCK_SEQPACKET, this call attempts to make a connection  to  the  socket
       that is bound to the address specified by addr.

       Generally,  connection-based protocol sockets may successfully connect()
       only once; connectionless protocol sockets may  use  connect()  multiple
       times  to change their association.  Connectionless sockets may dissolve
       the association by connecting to an address with the sa_family member of
       sockaddr set to AF_UNSPEC (supported on Linux since kernel 2.2).

TCP 通信流程分析: 

TCP 通信流程分析:
    Server:
        1.socket()      创建socket
        2.bind()        绑定服务器地址结构
        3.listen()      设置同时与服务器建立连接的上限数(监听上限)
        4.accept()      阻塞监听客户端连接
        5.read(fd)      读socket获取客户端数据
        6.小 -- 大写     toupper()
        7.write(fd)     
        8.close()


    Client:
        1.socket()       创建socket
        2.connect()      与服务器建立连接
        3.write()        写数据到socket
        4.read()         读转换后的数据
        5.显示读取结果
        6.close()
  • server.c
#include <arpa/inet.h>  
#include <unistd.h>  
#include <pthread.h>

#include <errno.h> 
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  

#include <ctype.h>  
#include <sys/socket.h>  

#define SERVER_PORT 9527

void sysErr(const char *msg) {
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[]) {
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (lfd == -1) sysErr("socket error");

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    //给服务器socket绑定地址结构
    int ret = bind(lfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
    if(ret == -1) sysErr("bind error");

    // 设置监听上限  
    ret = listen(lfd,128);
    if(ret == -1) sysErr("listen error");

    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);//  获取客户端地址结构大小
     // 阻塞等待客户端连接请求 
    int cfd = accept(lfd,(struct sockaddr*)&client_addr,&client_addr_len);
    if(cfd == -1) sysErr("accept error");
    // 根据accept传出参数,获取客户端 ip 和 port  
    char client_IP[1024];
    printf("client ip:%s port:%d\n",
        inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),
        ntohs(client_addr.sin_port));

    char buf[BUFSIZ];
    while(1) {
        ret = read(cfd,buf,sizeof(buf));
        write(STDOUT_FILENO,buf,ret);  // 写到屏幕查看

        // 转换为大写
        for(int i=0;i<ret;++i) {
            buf[i] = toupper(buf[i]); // 小写 -- 大写  
        }
        write(cfd,buf,ret);           // 将大写,写回给客户端
    }
    close(lfd);
    close(cfd);
    return 0;
}
  • client.c
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SERVER_PORT 9527

void sysErr(const char* msg) {
    perror(msg);
    exit(EXIT_FAILURE);// EXIT_FAILURE	1
}

int main(int argc, char const *argv[]) {
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1) sysErr("socket error");
    struct sockaddr_in server_addr; // 服务器地址结构
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr.s_addr);
    
    int ret = connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if(ret == -1) sysErr("connect error");

    int counter = 10;
    char buf[BUFSIZ];
    while(counter--) {
        char *msg = "hello server\n";
        write(cfd,msg,strlen(msg));
        ret = read(cfd,buf,sizeof(buf));
        write(STDOUT_FILENO,buf,ret);
        sleep(1);
    }
    close(cfd);
    return 0;
}
heheda@linux:~/Linux/test$ gcc server.c -o server -Wall -g
heheda@linux:~/Linux/test$ ./server 
heheda@linux:~/Linux/test$ gcc client.c -o client -Wall -g
heheda@linux:~/Linux/test$ ./client

未完待续~ 

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

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

相关文章

GPT3.5\GPT4系列计算完整prompt token数的官方方法

前言: ChatGPT如何计算token数&#xff1f;https://wtl4it.blog.csdn.net/article/details/135116493?spm1001.2014.3001.5502https://wtl4it.blog.csdn.net/article/details/135116493?spm1001.2014.3001.5502 GPT3.5\GPT4系列计算完整prompt token数的官方方法&#xff1…

Unity3d C# 在WebGL平台加载并解析xml文件实现总结

前言 xml是可扩展标记语言&#xff0c;由一系列的元素、属性、值节点等构成的一个树形结构&#xff0c;除了可读性差一点&#xff0c;别的用于存储一些结构化的数据还是比较方便的。这个功能在Unity3d端的实现是比较方便快捷的&#xff1a; void GetXML1() {string filePath …

K8S之Pod的介绍和使用

Pod的理论和实操 pod理论说明Pod介绍Pod运行与管理Pod管理多个容器Pod网络Pod存储 Pod工作方式自主式Pod控制器管理的Pod&#xff08;常用&#xff09; 创建pod的流程 pod实操通过资源清单文件创建自主式pod通过kubectl run创建Pod&#xff08;不常用&#xff09; pod理论说明 …

Unity根据落点和抛物线运行时间,求初始力

抛物线运行时长为2秒&#xff1a; 抛物线运行时长为4秒&#xff1a; 原理就是&#xff1a; 在竖直方向只受重力&#xff0c;做匀加速直线运动&#xff0c;水平不受力&#xff0c;做匀速直线运动。 代码&#xff1a; public void Update(){if (Input.GetKeyDown(KeyCode.Space)…

2024.1.30报错记录

今天想调通一套github上的U-net代码&#xff0c;把报错记录一下 第一章 ModuleNotFoundError: No module named skimage 没有这个模块 pip install scikit-image 第二章 TypeError: (‘Keyword argument not understood:‘, ‘input‘) TypeError: (‘Keyword argument …

数据图表方案,企业视频生产数据可视化

在信息爆炸的时代&#xff0c;如何将复杂的数据转化为直观、生动的视觉信息&#xff0c;是企业在数字化转型中面临的挑战。美摄科技凭借其独特的数据图表方案&#xff0c;为企业在数据可视化领域打开了一扇全新的大门。 一、数据图表方案的优势 1、高效便捷&#xff1a;利用数…

文件上传的另类应用

1.Imagemagick CVE-2016-3714 CVE-2022-44268 CVE-2020-29599可在vulhub靶场进行复现1.1.Imagemagick简介 ImageMagic是一款图片处理工具&#xff0c;当传入一个恶意图片时&#xff0c;就有可能存在命令注入漏洞。 ImageMagick默认支持一种图片格式mvg&#xff0c;而mvg与svg…

yii2 mongodb 操作

->where([<>,review,""]) 不等于空 $where [newstypeid>[$in>$categoryIdArr]]; 类似mysql in操作 &#xff08;$categoryIdArr是数组&#xff09; ->where([label>[$regex >赞美诗]]) 模糊搜索操作 $where [status>1,name>[$rege…

sentinel的Context创建流程分析

sentinel入门 功能 限流&#xff1a;通过限制请求速率、并发数或者用户数量来控制系统的流量&#xff0c;防止系统因为流量过大而崩溃或无响应的情况发生。 熔断&#xff1a;在系统出现故障或异常时将故障节点从系统中断开&#xff0c;从而保证系统的可用性。 降级&#xf…

Redis 的持久化机制是什么?各自的优缺点?

Redis 提供两种持久化机制 RDB&#xff08;默认&#xff09; 和 AOF 机制: RDB&#xff1a;是Redis DataBase缩写快照 RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中&#xff0c;对应产生的数据文件为dump.rdb。通过配置文件中的save参数来…

记录在树莓派中部署PI-Assistant开源项目(GPT语音对话)的BUG

核心 在部署PI-Assistant&#xff08;https://github.com/Lucky-183/PI-Assistant&#xff09;项目中&#xff0c;首先要进行环境安装&#xff0c;官网文档中提供的安装命令如下&#xff1a; pip install requests arcade RPi.GPIO pydub numpy wave sounddevice pymysql cn2…

20.HarmonyOS App(JAVA)表格布局Layout使用方法

ability_main.xml&#xff0c;实现计算器键盘按钮 <?xml version"1.0" encoding"utf-8"?> <TableLayoutxmlns:ohos"http://schemas.huawei.com/res/ohos"ohos:height"match_parent"ohos:width"match_parent"oho…

深度学习手写字符识别:训练模型

说明 本篇博客主要是跟着B站中国计量大学杨老师的视频实战深度学习手写字符识别。 第一个深度学习实例手写字符识别 深度学习环境配置 可以参考下篇博客&#xff0c;网上也有很多教程&#xff0c;很容易搭建好深度学习的环境。 Windows11搭建GPU版本PyTorch环境详细过程 数…

【数据分析】Excel中的常用函数公式总结

目录 0 引用方式0.1 相对引用0.2 绝对引用0.3 混合引用0.4 3D引用0.5 命名引用 1 基础函数1.1 加法、减法、乘法和除法1.2 平均数1.3 求和1.4 最大值和最小值 2 文本函数2.1 合并单元格内容2.2 查找2.3 替换 3 逻辑函数3.1 IF函数3.2 AND和OR函数3.3 IFERROR函数 4 统计函数4.1…

java设计模式:策略模式

在平常的开发工作中&#xff0c;经常会用到不同的设计模式&#xff0c;合理的使用设计模式&#xff0c;可以提高开发效率&#xff0c;提高代码质量&#xff0c;提高代码的可拓展性和维护性。今天来聊聊策略模式。 策略模式是一种行为型设计模式&#xff0c;运行时可以根据需求动…

分布式session 笔记

概念 解决方案‘ 复制 session同步&#xff0c;让集群下的服务器进行session同步&#xff0c;一种传统的服务器集群session管理机制&#xff0c;常用于服务器不多的集群环境。<br /> 集群下&#xff0c;进行session同步的服务器的session数据是相同的&#xff0c;…

vulhub中spring的CVE-2022-22947漏洞复现

Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本&#xff08;包含&#xff09;以前存在一处SpEL表达式注入漏洞&#xff0c;当攻击者可以访问Actuator API的情况下&#xff0c;将可以利用该漏洞执行任意命令。 参考链接&#xff1a; https://tanzu.vmware.c…

图论练习1

内容&#xff1a;&#xff0c;拆点&#xff0c;分层&#xff0c;传递&#xff0c;带限制的最小生成树 [HNOI2015]菜肴制作 题目链接 题目大意 有个限制&#xff0c;号菜肴在号前完成在满足限制的条件下&#xff0c;按照出菜( 是为了满足的限制 ) 解题思路 由限制&#xf…

寒假 day1

1、请简述栈区和堆区的区别? 2、有一个整形数组:int arr[](数组的值由外部输入决定)&#xff0c;一个整型变量: x(也 由外部输入决定)。要求: 1)删除数组中与x的值相等的元素 2)不得创建新的数组 3)最多只允许使用单层循环 4)无需考虑超出新数组长度后面的元素&#xff0c;所以…

2024美赛数学建模D题思路分析 - 大湖区水资源问题

1 赛题 问题D&#xff1a;大湖区水资源问题 背景 美国和加拿大的五大湖是世界上最大的淡水湖群。这五个湖泊和连接的水道构成了一个巨大的流域&#xff0c;其中包含了这两个国家的许多大城市地区&#xff0c;气候和局部天气条件不同。 这些湖泊的水被用于许多用途&#xff0…