Linux C++网络编程(一)

最近要准备面试了,总结一下Linux网络编程。

一、常用的结构体和API

结构体

1.sockaddr_in

结构体通常用于在IPv4套接字编程中表示地址信息。主要包括sin_family(地址族)、sin_addr(地址)、sin_port(端口号)。注意sin_family用__SOCKADDR_COMMON添加,会根据不同的操作系统进行适配。sin_addr里面只有一个s_addr。

struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;			/* Port number.  */
    struct in_addr sin_addr;		/* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr)
			   - __SOCKADDR_COMMON_SIZE
			   - sizeof (in_port_t)
			   - sizeof (struct in_addr)];
  };
  
struct in_addr
  {
    in_addr_t s_addr;
  };

2. fd_set

用来存储套接字的结构体。
常见的操作有:
FD_ZERO(fd_set *set):清空给定的文件描述符集合。
FD_SET(int fd, fd_set *set):在集合中设置指定的文件描述符。
FD_CLR(int fd, fd_set *set):从集合中清除指定的文件描述符。
FD_ISSET(int fd, fd_set *set):测试集合中指定的文件描述符是否被设置,即是否可操作。

3. pollfd

用于监听一个或者多个文件描述符的读写异常的结构体。

struct pollfd {
    int   fd;         // 文件描述符
    short events;     // 监听的事件,比如POLLIN表示可读,POLLOUT表示可写
    short revents;    // 实际发生的事件,返回时填充
};

fd:这是要监控的文件描述符。它可以是任何支持I/O操作的文件描述符,例如socket、管道、标准输入输出等。
events:这是一个位掩码,指定了我们对这个文件描述符感兴趣的事件。常见的事件有:
POLLIN:表示关心文件描述符是否可读。
POLLOUT:表示关心文件描述符是否可写。
POLLPRI:表示关注有优先级的可读事件,通常用于带外数据。
POLLERR:表示关心错误条件。
POLLHUP:挂断事件,对端关闭连接。
POLLNVAL:无效的文件描述符。
revents:这是一个输出字段,由poll()函数填充,表示在调用期间实际发生的事件。它包含了events中请求的事件中实际发生的一个子集,也可能包含其他意外事件,如POLLERR。

4. epoll_event

用于存储与文件描述符关联的事件类型以及相关的用户数据

typedef union epoll_data
{
  void *ptr;
  int fd;
  uint32_t u32;
  uint64_t u64;
} epoll_data_t;

struct epoll_event
{
  uint32_t events;	/* Epoll events */
  epoll_data_t data;	/* User data variable */
} __EPOLL_PACKED;

网络编程函数API

1. socket

用于创建套接字。每个连接都有一个独立的套接字,类似句柄。

例如:int sockfd = socket(AF_INET, SOCK_STREAM, 0);

第一个参数是domain(域):这个参数指定了使用的协议族或地址族。常见的取值包括AF_INET(IPv4地址族)、AF_INET6(IPv6地址族)、AF_UNIX(本地通信的UNIX域套接字)等。
第二个参数是type(类型):这个参数指定了套接字的类型,常见的取值包括SOCK_STREAM(流式套接字,使用TCP)和SOCK_DGRAM(数据报套接字,使用UDP)。
第三个参数是protocol(协议):通常情况下可以指定为0,表示根据前两个参数选择默认的协议。

2. bind

把某个套接字绑定到一个初始化后的sockaddr_in上。

例如:bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)

其中 sockfd 是一个文件描述符,代表需要绑定地址的套接字,addr 是一个指向存放地址信息的结构体的指针,addrlen 是地址结构体的长度。第三个参数用于更好的计算结构体的地址。

3. listen

启动套接字监听模式,以便可以接受客户端的连接请求。

例如:listen(sockfd, 10);

其中第二个参数是等待连接队列的最大长度,超过会返回拒接连接的错误

4.accept

接受客户端请求并且声称一个新的套接字描述符。注意和socket的区别,socket绑定的是本地服务器的地址,accept返回值对应的的是客户端的地址。
例如:
struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);
其中sockfd是一个文件描述符,由socket创建。clientaddr:这是一个指向struct sockaddr结构体的指针,用于接收连接的客户端的地址信息。len:这是一个指向socklen_t(或某些系统上的size_t)类型的指针,用于指定clientaddr指向的地址结构的大小。

5. recv

函数定义:ssize_t recv(int socket, void *buffer, size_t length, int flags);
int count = recv(clientfd, buffer, 1024, 0);
从一个已连接的客户端接收数据。buffer是缓冲区指针,1024是缓冲区大小。

6. send

函数定义:send(int socket, const void *buffer, size_t length, int flags);
int count = send(clientfd, buffer, count, 0);
向客户端发送数据

7.select

函数定义:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
int nready = select(maxfd+1, &rset, NULL, NULL, NULL);
返回已经准备就绪的文件描述符的个数。
第一个参数是所有文件描述符里最大值+1,这是因为文件描述符是从0开始计算的。
第二个参数是指向 fd_set 结构体的指针,表示关注可读文件描述符集合。当 select() 返回时,这个集合会被修改,只保留那些当前可读的文件描述符。
第三个参数 writefds 是指向一个 fd_set 的指针,用于监控可写的文件描述符。这里传入 NULL 意味着我们不关心任何文件描述符的写就绪状态。
第四个参数 exceptfds 同样是指向一个 fd_set 的指针,用于监控异常条件(如断开连接)。传入 NULL 表示我们也不关心异常事件。
第五个参数 timeout 是一个指向 struct timeval 的指针,用于设置 select() 的超时时间。传入 NULL 表示阻塞直到至少有一个文件描述符变为可读、可写或有异常。

8. poll

select函数的改进版本,主要解决了select文件描述符限制的问题。
函数定义:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
int nready = poll(fds, maxfd+1, -1);
fds: 一个指向pollfd结构体数组的指针。每个结构体定义了一个需要监控的文件描述符及其相关的事件。
nfds: 数组fds中的元素数量。这个值应该是你实际要监控的文件描述符的数量,而不是最大文件描述符值加1。
timeout: 超时时间,单位为毫秒。如果设为0,则poll立即返回;如果设为-1,则poll会一直阻塞直到有事件发生;如果是正数,则表示等待的最长时间,超时后poll也会返回。

9.epoll_create

epoll_create是Linux系统中用于创建一个 epoll 文件描述符的系统调用。
int epfd = epoll_create(1);
这里的参数传入一个正整数即可

10.epoll_ctl

epoll_ctl用于控制已经创建的epoll实例中的文件描述符集合。它允许用户添加、修改或删除对特定文件描述符的监控事件。
函数原型:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
第一个参数epfd是通过epoll_create得到的epoll文件描述符。
第二个参数EPOLL_CTL_ADD指定操作类型为添加监控。
第三个参数sockfd是要添加进epoll监控的文件描述符。可以理解为epoll实例和sockfd的绑定。
第四个参数&ev是指向epoll_event结构体的指针,包含了要监控的事件类型及关联数据。

11. epoll_wait

用于把准备就绪的事件放入某个数组中。
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

struct epoll_event events[1024] = {0};
int nready = epoll_wait(epfd, events, 1024, -1);

epfd:通过之前调用epoll_create(2)创建的epoll文件描述符。这是epoll实例的标识符。
events:一个指向epoll_event结构体数组的指针。当epoll_wait返回时,这个数组会被填充上就绪事件的信息。每个元素代表一个事件,包括触发事件的文件描述符和事件类型。
maxevents:epoll_wait调用可以返回的最大事件数量。这个参数限制了events数组的大小,防止数组溢出。
timeout:等待事件的超时时间,单位为毫秒。如果设为0,epoll_wait立即返回,无论是否有事件发生;如果设为-1,则表示无限期等待,直到至少有一个事件发生;如果是正数,则在指定的毫秒数后超时返回,即使没有事件发生。

这是一条吃饭视频,由挨踢零声赞助。

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux网络编程(总共41集) 讲解Linux网络编程知识,分以下四个篇章。 Linux网络编程之TCP/IP基础篇 Linux网络编程之socket编程篇 Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输单元(MTU)/路径MTU 以太网帧格式 ICMP ARP RARP 03TCPIP基础(三) IP数据报格式 网际校验和 路由 04TCPIP基础(四) TCP特点 TCP报文格式 连接建立三次握手 连接终止四次握手 TCP如何保证可靠性 05TCPIP基础(五) 滑动窗口协议 UDP特点 UDP报文格式 Linux网络编程之socket编程篇 06socket编程(一) 什么是socket IPv4套接口地址结构 网络字节序 字节序转换函数 地址转换函数 套接字类型 07socket编程(二) TCP客户/服务器模型 回射客户 /服务器 socket、bind、listen、accept、connect 08socket编程(三) SO_REUSEADDR 处理多客户连接(process-per-conection) 点对点聊天程序实现 09socket编程(四) 流协议与粘包 粘包产生的原因 粘包处理方案 readn writen 回射客户/服务器 10socket编程(五) read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程与SIGCHLD信号 12socket编程(七) TCP 11种状态 连接建立三次握手、连接终止四次握手 TIME_WAIT与SO_REUSEADDR SIGPIPE 13socket编程(八) 五种I/O模型 select 用select改进回射客户端程序 14socket编程(九) select 读、写、异常事件发生条件 用select改进回射服务器程序。 15socket编程(十) 用select改进第八章点对点聊天程序 16socket编程(十一) 套接字I/O超时设置方法 用select实现超时 read_timeout函数封装 write_timeout函数封装 accept_timeout函数封装 connect_timeout函数封装 17socket编程(十二) select限制 poll 18socket编程(十三) epoll使用 epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 Linux网络编程之进程间通信篇 23进程间通信介绍(一) 进程同步与进程互斥 进程间通信目的 进程间通信发展 进程间通信分类 进程间共享信息的三种方式 IPC对象的持续性 24进程间通信介绍(二) 死锁 信号量 PV原语 用PV原语解决司机与售票员问题 用PV原语解决民航售票问题 用PV原语解决汽车租赁问题 25System V消息队列(一) 消息队列 IPC对象数据结构 消息队列结构 消息队列在内核中的表示 消息队列函数 26System V消息队列(二) msgsnd函数 msgrcv函数 27System V消息队列(三) 消息队列实现回射客户/服务器 28共享内存介绍 共享内存 共享内存示意图 管道、消息队列与共享内存传递数据对比 mmap函数 munmap函数 msync函数 29System V共享内存 共享内存数据结构 共享内存函数 共享内存示例 30System V信号量(一) 信
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值