一、socket

socket 网络套接字一个文件文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现(接收缓冲区和发送缓冲区))通讯过程中,套接字一定是 【成对】 出现的。

二、网络字节序


小端法(PC本地存储):   高位存高地址。低位存低地址。
大端法(网络存储):         高位存低地址。低位存高地址。涉及的四个函数:man htonl1.NAMEhtonl, htons, ntohl, ntohs - convert values between host and network byte order2.SYNOPSIS#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong); //本地->网络(IP) converts the unsigned integer hostlong from host byte order to network byte order.//这里的IP指的不是192.168.1.1这样的字符串形式uint16_t htons(uint16_t hostshort);   //本地->网络(Port) converts the unsigned short integer hostshort from host byte order to network byte order.uint32_t ntohl(uint32_t netlong);  //网络->本地(IP) converts the unsigned integer netlong from network byte order to host byte order.uint16_t ntohs(uint16_t netshort);   //网络->本地(Port) converts the unsigned short integer netshort from network byte order to host byte order.

三、IP地址转换函数

主机字节序(小端)和网络字节序(大端)相互转换时,需要用到此节提到的转换函数。
1.inet_pton()//本地字节序(string IP)-> 网络字节序//客户端connect()函数会用到man inet_pton1)NAMEinet_pton - convert IPv4 and IPv6 addresses from text to binary form2)SYNOPSIS#include <arpa/inet.h>int inet_pton(int af, const char *src, void *dst);3)PARAMETERaf:指定IP协议AF_INET  IPv4AF_INET6 IPv6src:传入IP地址(点分十进制,192.168.1.1)dst:值结果参数,传出转换后的网络字节序 IP 地址。4)RETURN VALUEinet_pton() returns  1 on success (network address was successfully converted).  0 is returned if src does not contain a character string repre‐senting a valid network address in the specified address family.  If af does not contain a valid address family, -1 is returned and errno is  set to EAFNOSUPPORT.                 2.inet_ntop() //网络字节序-> 本地字节序(string IP)//服务端accept()函数会用到1)NAMEinet_ntop - convert IPv4 and IPv6 addresses from binary to text form2)SYNOPSIS#include <arpa/inet.h>const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);3)PARAMETERaf:指定IP协议AF_INET  IPv4AF_INET6 IPv6src: 传入网络字节序 IP 地址dst:值结果参数,传出转换后的IP地址(点分十进制,192.168.1.1)。4)RETURN VALUEOn success, inet_ntop() returns a non-null pointer to dst.  NULL is returned if there was an error, with errno set to indicate the error.

四、sockaddr 和 sockaddr_in 地址结构体

  1. sockaddr 和 sockaddr_in 区别

    大小相同,都是16字节。
    区别在于:sockaddr 诞生日期早,底层封装应用的多。sockaddr_in 后来诞生,更精细化,现在更常用。故现在使用的都是 sockaddr_in,但在bind(),accept()时都需要将sockaddr_in强转为sockaddr才行 。
    

  1. sockaddr_in结构体详解

    man 7 ip  //查看 sockaddr_in 信息struct sockaddr_in {sa_family_t    sin_family; /* address family: AF_INET */in_port_t      sin_port;   /* port in network byte order */struct in_addr sin_addr;   /* internet address */};/* Internet address. */struct in_addr {uint32_t       s_addr;     /* address in network byte order */};
  2. 实际应用

    man 7 ip  //查看 sockaddr_in 信息实际应用步骤如下:1.定义并赋值 sockaddr_in 结构体2.将 socketaddr_in 强转为 sockaddr 指针类型。示例:struct sockaddr_in addr;addr.sin_family = AF_INET; //AF_INET6addr.sin_port = htons(8080);/* 方式 1,这种不常用。inet_pton(AF_INET,"10.219.10.193",(void*)&addr_s.sin_addr);或者int dst;inet_pton(AF_INET,"192.168.1.1",(void*)dst);addr.sin_addr.s_addr = dst;*///方式2 ,这是常用方式。addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY 取系统中有效的任意IP地址,二进制类型。bind(fd,(struct sockaddr*)addr,size);

五、服务端和客户端通讯

 一般通讯由 3 个描述符组成。一对用于客户端和服务器通讯,一个用于监听。listen()函数的作用是设置监听上线(同一时刻接收到连接的个数),而不是设置监听。accept()函数才是阻塞监听客户端连接。accept()接收到客户端connect()连接后会生成一个新的socket用于通讯,而accept()调用的 fd 会返回继续进行监听。客户端在connect()前没有显示bind()绑定客户端地址,那采用的就是“隐式绑定”。


六、TCP网络编程涉及函数

  1. socket

    man 2 socket1.NAMEsocket - create an endpoint for communication2.SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol);
    3.PARAMETERdomain:      常用的有3个:AF_UNIX //Local communication   AF_INET //IPv4 Internet protocolsAF_INET6 //IPv6 Internet protocols                            type: 常用的有2个:SOCK_STREAM //流 TCPSOCK_DGRAM //报文 UDPprotocol:默认 0 即可。 //所选用协议的代表协议是什么,也就是type对应的协议。0就是默认的指代。默认:SOCK_STREAM -> TCP ;SOCK_DGRAM -> UDP.
    4.RTETURN VALUEOn success, a file descriptor for the new socket is returned.  On error, -1 is returned, and errno is set appropriately.
    
  2. bind

    man 2 bind1.NAMEbind - bind a name to a socket2.SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    3.PARAMETERsockfd: socket函数返回值struct sockaddr_in addr;addr.sinfamily = AF_INET;addr.sin_port = htons(8888);addr.sin_addr.s_addr = htonl(INADDR_ANY); //系统自行选择IPinet_pton(AF_INET,"10.219.10.193",(void*)&addr_s.sin_addr); //指定IPaddr:(struct sockaddr *)&addr addrlen:sizeof(addr)
    4.RETURN VALUEOn success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
    
  3. listen

    //设置同时与服务器建立连接的上线数 (同时进行三次握手的客户端数量)man 2 listen1.NAMElisten - listen for connections on a socket2.SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int listen(int sockfd, int backlog);
    3.PARAMETERsockfd: socket 函数返回值backlog:上线数。最大值为 128
    4.RETURN VALUEOn success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
    
  4. accept

    //阻塞等待客户端连接man 2 accept1.NAMEaccept, accept4 - accept a connection on a socket2.SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    3.PARAMETERsockfd  :socket函数返回值(也必须是listen过的fd)addr   :值结果参数。传出成功与服务器建立连接的客户端地址结构 addrlen :传入传出参数。传入:传入时addr的大小。一般为:sizeof(addr)传出:客户端addr的实际大小。
    4.RETURN VALUEOn success, these system calls return a nonnegative integer that is a file descriptor for the accepted socket.  On error, -1 is  returned,  errno is set appropriately, and addrlen is left unchanged.
    
  5. connect

    //使用创建的socket与服务器连接man 2 connect1.NAMEconnect - initiate a connection on a socket2.SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    3.PARAMETERsockfd   :socket函数返回值struct sockaddr_in addr; addr.sin_family = AF_INET;addr.sin_port = htons(atoi(argv[2])); inet_pton(AF_INET,argv[1],&addr.sin_addr.s_addr);addr    :传入参数。服务器地址结构。(也就是要连接的服务器的地址结构) 用inet_pton()给地址赋值。addrlen :服务器地址结构大小。
    4.RETURN VALUEIf the connection or binding succeeds, zero is returned.  On error, -1 is returned, and errno is set appropriately.注: 如果connect前未使用bind显示绑定客户端地址,采用的就是“隐式绑定”。
    
  6. 实现简单的服务器和客户端DEMO

    DEMO流程如下图所示:

DEMO:https://github.com/Panor520/LinuxCode/tree/master/socket/tcp/simpledemo

七、UDP网络编程涉及函数及DEMO

  1. socket
    同 tcp中的socket

  2. recvfrom

    man 2 recvfrom1.NAMErecv, recvfrom, recvmsg - receive a message from a socket2.SYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);3.PARAMETERsockfd  :通信的套接字buf       :缓冲区地址 //char buf[1024];len      :缓冲区大小   //sizeof(buf)flags  : 默认0.src_addr:(struct addr*)&addr_c 传出,对端地址结构 //不需要对端地址信息可置 0addrlen  :传入传出参数。 socklen_t len_addr_c;    //不需要对端地址信息可置 0
    4.RETURN VALUE成功    :成功接收数据字节数。失败    :-1 errno0       :对端关闭。
    
  3. sendto

man 2 sendto1.NAMEsend, sendto, sendmsg - send a message on a socket2.SYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);3.PARAMETERsockfd    :通信的套接字buf      :缓冲区地址 //char buf[1024];len     :缓冲区大小  //sizeof(buf)flags  :默认0.dest_addr:(struct addr*)&addr 传入,对端地址结构addrlen  :sizeof(addr).4.RETURN VALUE成功  :成功写如数据字节数失败 :-1. errno
  1. UDP通信DEMO
    server连接地址
    client连接地址

八、优化——自定义封装通讯函数


八、read函数返回值(必须掌握)

read函数返回值:>0   :实际读到的字节数=0    :已经读到结尾(对端已经关闭)【重!点!,必须掌握】-1 :进一步判断errno的值errno = EAGAIN or EWOULDBLOCK : 设置了非阻塞方式 读。没有数据到达errno = EINTR 慢速系统调用被 中断。errno = “其他情况” 异常。

九、多进程并发服务器

连接地址

十、多线程并发服务器

连接地址

十一、服务端端口和地址复用(设置套接字选项避免2MSL时长报错问题)

先关闭服务端,主动关闭端就会经历 TIMEWAIT 状态(2MSL时长),立即再次启动服务端时会出现bind server error的错误,
可以用下面方法避免。 详见 unix网络编程 第7章man setsockopt先前关闭的服务端还在经历 TIMEWAIT状态,只是 端口和地址可以复用。用法:在服务端的socket()和bind()调用之间插入如下代码:int opt = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

十二、close和shutdown区别

当使用dup2()指定多个整数指向同一个文件描述符时:close() 关闭只会关闭指定的那个。【单个关闭】shutdown()关闭时,会将所有指向该文件描述符的连接全部关闭。【全关闭】man 2 shutdown
1.NAMEshutdown - shut down part of a full-duplex connection2.SYNOPSIS#include <sys/socket.h>int shutdown(int sockfd, int how);
3.PARAMETERShow:SHUT_RD 关读端SHUT_WR 关写端SHUT_RDWR 两端都关闭
4.RETURN VALUEOn success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

十三、多路I/O转接 服务器(select、poll)

  1. 基础

    传统的 多线程和多进程服务器 就是是【阻塞】的。
    而 多路I/O转接(select、poll、epoll) 是【非阻塞】的。多路I/O转接 是由内核提供的 select、poll、epoll 监听机制。
    监听connect 事件及 read、write事件。只有当 client 发生相应事件时,多路转接实现的服务器才会响应。 平时是非阻塞的(不会一直等待)。select的实现如下图所示:
    

  1. select

    man 2 select1.NAMEselect, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing2.SYNOPSIS/* According to POSIX.1-2001, POSIX.1-2008 */#include <sys/select.h>/* According to earlier standards */#include <sys/time.h>#include <sys/types.h>#include <unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);void FD_CLR(int fd, fd_set *set);     //将一个文件描述符从集合中清除int  FD_ISSET(int fd, fd_set *set); //判断一个文件描述符是否在集合中void FD_SET(int fd, fd_set *set);  //将一个文件描述符添加到描述符集合中void FD_ZERO(fd_set *set);           //清空文件描述符集合3.PARAMETERnfds  :监听的所有文件描述符中,最大文件描述符+1。//例:要监听 4~50的文件描述符(47), nfds就应该填 48readfds    :读 文件描述符监听集合。        传入 传出 参数。 传入:要设置读监听的文件描述符集合传出:发生了读事件的文件描述符集合//例:传入集合中有4、5、6文件描述符。而4文件描述符发生了读事件,故传出的集合中只存在文件描述符4。writefds:写 文件描述符监听集合。        传入 传出参数传入:要设置写监听的文件描述符集合传出:发生了写时间的文件描述符集合//例:传入集合中有4、5、6文件描述符。而5文件描述符发生了写事件,故传出的集合中只存在文件描述符5。exceptfds:异常 文件描述符集合。       传入  传出  参数。传入:要设置异常监听的文件描述符集合传出:发生了异常事件 的文件描述符集合//例:传入集合中有4、5、6文件描述符。而6文件描述符发生了异常事件,故传出的集合中只存在文件描述符6。timeout:    >0   :设置监听时长NULL:阻塞监听(也就是始终等待事件发生)0  :非阻塞监听,轮询4.fd_set是一个位图。 0 1表示。5.RETURN VALUE>0 :所有监听集合(3个)中,所有传出集合的文件描述符的总数。//例:以上面参数的例子为例,三个集合共传出了4、5、6故RETURN VALUE=3.=0 :没有满足监听条件的文件描述符=-1  :ERROR. errno.
    

    select服务器DEMO思路分析:

    基础select demo实现链接
    升级版select demo实现链接

    select
    缺点 监听上限受文件描述符限制,最大 1024。检测满足条件的fd,需自己增加业务逻辑提高效率,也是变向增加了编码难度
    优点 跨平台。可在 windowns、linux、macOS、Unix、类Unix、mips 上运行
  2. poll

    poll 就是升级版select (增加数组记录要遍历的文件描述符)man poll 1.NAMEpoll, ppoll - wait for some event on a file descriptor2.SYNOPSIS#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);
    3.PARAMETERfds  :监听的文件描述符【数组】struct pollfd {int   fd;         /* file descriptor */ //待监听的文件描述符short events;     /* requested events */ //待监听的文件描述符对应的监听事件short revents;    /* returned events */ //传入0。如果满足events给定的事件,会返回events对应的传入值。};events 或 revents 取值: POLLIN  //读事件POLLOUT    //写事件POLLERR    //错误事件nfds:监听数组的 实际有效监听个数。timeout: >0 :超时时长。 单位:毫秒。-1 :阻塞等待。0  :不阻塞。
    4.RETURN VALUE满足对应监听事件的文件描述符 【总个数】。
    

    poll demo实现链接

    poll
    缺点 不能跨平台。只能在Linux或类Unix上运行。 不能直接定位到满足事件的文件描述符,也是变向增加了编码难度
    优点 自带数组结构。可以将 监听事件集合 和 返回事件集合 分离。 可拓展 监听上线(方法同epoll)(超出1024限制)

十四、epoll

  1. 基础

    epoll的本质是一个【红黑树】。监听结点为根节点。
    
       epoll的使用由三个函数组成。//epoll 应该使用非阻塞的ET模式写服务器程序(这是规则)man epoll_createman epoll_ctlman epoll_wait1.epoll_create() //创建一棵监听红黑树1)NAMEepoll_create, epoll_create1 - open an epoll file descriptor2)SYNOPSIS#include <sys/epoll.h>int epoll_create(int size);3)PARAMETERsize:创建红黑树的监听结点数量 (仅供内核初始化使用,当实际使用超出该大小时,内核会自动扩容)4)RETURN VALUEOn success, these system calls return a nonnegative file descriptor.  On error, -1 is returned, and errno is set to indicate the error.2.epoll_ctl() //操作监听红黑树1)NAMEepoll_ctl - control interface for an epoll file descriptor2)SYNOPSIS#include <sys/epoll.h>int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);3)PARAMETER1.epfd    :epoll_create()函数的返回值2.op       :对该监听红黑树所做的操作。有三种值:EPOLL_CTL_ADD //添加 fd 到监听红黑树EPOLL_CTL_MOD //修改 fd 在监听红黑树上的监听事件EPOLL_CTL_DEL //将一个 fd 从监听红黑树上摘下(取消监听)3.fd        :待 op 操作的fd4.event   :本质为 struct epoll_event 结构体 指针。struct epoll_event {uint32_t     events;      /* Epoll events */epoll_data_t data;        /* User data variable */};成员 events 常用值:EPOLLINEPOLLOUTEPOLLERR成员 data 原型如下:typedef union epoll_data {void        *ptr;int          fd; //对应监听事件的fduint32_t     u32;//不用uint64_t     u64;//不用} epoll_data_t;4)RETURN VALUEWhen successful, epoll_ctl() returns zero.  When an error occurs, epoll_ctl() returns -1 and errno is set appropriately.3.epoll_wait()  //阻塞监听红黑树1)NAMEepoll_wait, epoll_pwait - wait for an I/O event on an epoll file descriptor2)SYNOPSIS#include <sys/epoll.h>int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);                    3)PARAMETER1.epfd   :epoll_create()函数的返回值2.events   :传出参数(数组),满足定义的监听事件的所有结点的结构体数组3.maxevents:events 数组元素的总个数。 默认为1024 。struct epoll_event events[1024];4.timeout  : -1    :阻塞0    :不阻塞-1   :失败 errno.                   4)RETURN VALUE>0 :满足监听事件的struct epoll_event结构体的总个数。可用作循环处理的上线。0  :没有满足监听事件的struct epoll_event结构体-1   :失败 errno
    
    epoll
    缺点
    优点

    基础epoll demo实现链接

  2. epoll 事件模型

      ET 模式:      (服务器常用方式)      即边沿触发。 缓冲区剩余未读尽的数据不会导致 epoll_wait 返回。新的事件满足才会触发。设置方式:struct epoll_event event;event.events = EPOLLIN | EPOLLET;注意: ET模式只支持非阻塞。需给连接的文件描述符设置读写非阻塞(利用fcntl函数),如下:epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &event);int flg = fcntl(cfd, F_GETFL);flg |= O_NONBLOCK; //位或操作fcntl(cfd, F_SETFL, flg);LT 模式:即水平触发。 ---epoll默认采用方式缓冲区剩余未读尽的数据会导致 epoll_wait 返回。 例:通信时,readn 读数据时,每次只读 100字节,但缓冲区接收了 250 字节。① 默认的 LT模式下 会直接 再次触发 epoll_wait()函数,表明该连接fd又有数据写过来,并再读出100字节,之后再次触发 epoll_wait()函数,表明又有数据写过来,接收50字节后会阻塞在readn的地方,直到写满100字节。一旦 阻塞在readn的地方,代码就会有问题,因为应该阻塞在epoll_wait()的地方。② 在 ET模式下,剩下的150字节会被读取忽略,不会触发 epoll_wait()函数,而下次在写入数据时,会再从之前的150字节里读前100字节,后面的新写入的数据累加进来,等待下次在读取100字节。
    

    【总结:应使用非阻塞的 ET模式写epoll服务器。】

  3. epoll 反应堆

    就是epoll基础demo的升级版,更完整些。
    也是libevent 框架采用的方式。epoll反应堆:ET模式 + 非阻塞、轮询 + void *ptr. 简单的 epoll demo:socket、bind、listen   --  epoll_create 创建监听红黑树    -- 返回 epfd  --  epoll_ctl() 向树上添加一个监听fd ----    while(1)    --  epoll_wait 监听   --  对应监听fd有事件产生 -- 返回监听满足数组。 -- 判断返回数组元素    ----    lfd满足 --  Accept    --  cfd满足   -- read -- 小--大 -       【diff content】  - write回去。反应堆:反应堆的优化就是在检测到对端有数据传输过来后,服务端写回时要检测,对端是否可写,确认可写再将数据写过去。socket、bind、listen    --  epoll_create 创建监听红黑树    -- 返回 epfd  --  epoll_ctl() 向树上添加一个监听fd ----    while(1)    --  epoll_wait 监听   --  对应监听fd有事件产生 -- 返回监听满足数组。 -- 判断返回数组元素    ----    lfd满足 --  Accept    --  cfd满足   -- read -- 小--大 --   【diff begin】-- cfd从监听红黑树上摘下    --  EPOLLOUT    --  回调函数    --epoll_ctl()   -- EPOLL_CTL_ADD重新放到红黑树上监听 ---- 等待  epoll_wait() 返回 -- 说明 cfd 可写 -- write写回去--  cfd 从监听红黑树上摘下   --  EPOLLIN | EPOLLET   --  epoll_ctl() --  EPOLL_CTL_ADD   重新放到红黑上监听读事件    --  epoll_wait()监听      【diff end】
    

    反应堆epoll demo实现链接

Linux网络编程——socket编程相关推荐

  1. [linux] Linux网络之Socket编程入门

    目录 1. 前言 2. 网络基础 2.1 协议 2.1.1 TCP和UDP协议 2.2 网络的层状结构 2.3 一台主机向另一台主机的发送数据的流向 2.4 IP和MAC地址 2.5 端口 2.6 网 ...

  2. Linux网络原理与编程——第十一节 网络基础及套接字

    目录 一.网络的层状划分结构 二.网络发展史 三.协议 四.OSI七层结构模型 五.TCP/IP四层(五层)协议结构模型 六.局域网中通信原理初识 封包.解包.分用.mac帧 七.跨网络通信原理初始 ...

  3. Linux下简单socket编程

    Linux下简单socket编程 socket的英文翻译是接口.插座的意思,很形象,就相当于将两个台电脑用一根线连起来,线的两头分别是插头,插在两台电脑上,借此实现通信. 两台电脑通信,实际上是这两台 ...

  4. Java网络编程——Socket 编程

    Socket 编程 Socket编程是在TCP/IP上的网络编程,但是Socket在上述模型的什么位置呢.这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来 我们可以发现Socket就在 ...

  5. Linux网络编程 | Socket编程(一):Socket的介绍、UDPSocket的封装、UDP服务器/客户端的实现

    目录 套接字编程 Sockaddr结构 字节序 地址转换 常用套接字接口 UDP的通信流程 UDPSocket的封装 UDP服务器 UDP客户端 套接字编程 所谓套接字(Socket),就是对网络中不 ...

  6. linux C语言 socket编程教程(附两个例子)(socket教程)

    文章目录 1.网络中进程之间如何通信? 2.什么是Socket? 3.socket的基本操作 3.1.socket()函数 3.2.bind()函数 网络字节序与主机字节序 3.3.listen(). ...

  7. python网络编程-socket编程

    一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层模 ...

  8. Linux学习之socket编程(一)

    socket编程 socket的概念: 在TCP/IP协议中,"IP地址+TCP或UDP端口号"唯一标识网络通讯中的一个进程,"IP地址+端口号"就称为sock ...

  9. 初识网络及socket编程基础

    理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址. 源ip地址就是发送端ip,目的ip地址就是接收端ip 思考: 我们光有IP地址就可以完成通 ...

  10. 网络基础+Socket编程+高并发服务器

    网络编程 P1 复习 Linux 网络编程 P2 信号量生产者复习 P3 协议 P4 七层模型和四层模型及代表协议 P5 网络传输数据封装流程 P6 以太网帧和ARP请求 P7 IP 协议 P8 TC ...

最新文章

  1. Windows下搭建FTP服务器
  2. React之回调函数形式的ref
  3. linux控制流程,Linux - Bash - 流程控制
  4. HG20615法兰数据注意事项
  5. hive 创建外部表产生java_(一)Hive表(管理表、外部表)的创建规则
  6. 【Python】单引号、双引号、三引号和字符串
  7. leetcode题解46-全排列
  8. Java基础学习总结(122)——Java八种基本数据类型的包装类及其装箱拆箱详解
  9. 无人驾驶(pid算法)
  10. 【异常】No suitable driver
  11. 剑指 Offer II 083. 没有重复元素集合的全排列
  12. 大数据中mapreduce的核心,shuffle的理解,以及在shuffle中的优化问题
  13. 怎样用计算机打出seeyouagain,怎么唱好seeyouagain说唱
  14. OC试题 ——通讯录(AddressBook)
  15. java 对象逃逸 解决_Java中的逃逸问题心得
  16. STM32模拟IIC读取PCF8563
  17. 路肩石水渠机在施工公路项目中工艺特点的匹配
  18. 外仁内圣,以借得天下,以情御英雄
  19. 【工作需要】CAD+VBA 实现图块的旋转平移缩放和拼接
  20. 计算机毕业设计Python+uniapp快递寄取微信小程序(小程序+源码+LW)

热门文章

  1. javplayer手机版怎么用_JavPlayerTrial
  2. 俺把所有粉丝显示在地图上啦~【详细教程+完整源码】
  3. C++语言SetCurrentDir(ExtractFilePath(Application-ExeName))这句是什么意思
  4. 股票行情数据接口软件只能由券商提供吗?
  5. 【windows7】笔记本电脑没声音了怎么办
  6. 达人评测酷睿i5 12450h和锐龙R5 6600H选哪个
  7. linux如何中断硬盘检测程序,Linux检测硬盘坏道 与 修复
  8. java浮点数数转二进制的数吗_都工作两年了,还不知道浮点数如何转二进制?...
  9. [转载]点阵图(位图)与矢量图的区别
  10. 面试君与面试官的分歧:innodb支持行锁就不锁表么?