Linux环境编程之三

7. 网络通信

简介

主要对socket套接字进行详细的分析,包括连接的建立、数据的发送与接收等等。

连接的建立socket

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

第1个参数domain:用于表示协议族,如AF_INET为IPv4

第2个参数type: 用于指示类型,如基于流通信的SOCK_STREAM

第3个参数protocal: 对应这种socket的具体协议类型。

成功创建socket后,会返回一个套接字文件描述符。失败时,接口返回-1。

绑定IP地址bind

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

第1个参数sockfd:表示要绑定地址的套接字描述符

第2个参数addr:表示绑定到套接字的地址

struct sockadd {
    sa_family_t sa_family;
    char sa_data[14];
}

第3个参数addrlen: 表示绑定的地址长度

成功返回0,错误返回-1。

成功创建套接字后,该套接字仅仅是一个文件描述符,并没有任何地址与之关联,使用socket发送数据包时,由于该socket没有任何ip地址,内核会自动选择一个地址。一般对于服务端需要通过bind手动指定地址。

客户端连接connect

#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,  socklen_t addrlen);

第1个参数 sockfd:套接字描述符

第2个参数 addr:要连接的地址

第3个参数addrlen:要连接的地址长度

对于TCP套接字来说,connect是3次握手,所以其默认是一个阻塞操作。也可以成为一个非阻塞的过程。

服务器监听listen

#include <sys/socket.h>
int listen(int sockfd, int backlog);

第1个参数sockfd:成功创建的TCP套接字

第2个参数backlog:定义TCP未处理连接的队列长度,该队列已经完成三次握手,但服务器端还没有执行accept的连接。

成功返回0,失败返回-1。

服务器连接accept

#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

第1个参数sockfd:处于监听状态的套接字

第2个参数addr:保存客户端的地址信息

第3个参数addrlen:是一个输入输出值,调用者将其初始化为addr缓存的大小,accept返回时,设置为addr的大小。

第4个参数flags:accept4的标志,目前支持SOCK_NONBLOCK、SOCK_CLOEXEC。

成功返回一个非负的文件描述符,失败返回-1。

accept用于从指定套接字的连接队列中取出第一个连接,并返回一个新的套接字用于与客户端通信。

发送相关接口send

#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);
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

send只能用于处理已经连接的套接字。

sendto可以在调用时指定目的地址,如果套接字已经是连接状态,那么目的地址的dest_addr与addrlen应该是NULL和0。

sendmsg无论要发送的数据还是目的地址都保存在msg中,msg.msg_name和msg.msg_len用于指明目的地址,而msg.msg_iov用于保存要发送的数据。

flags只是标志位(稍现代的系统调用,一般都会有一个标志参数,可以从容的为系统调用增加新功能,并同时兼容老版本)

由于socket同时还是文件描述符,所以为文件提供的读写函数,也可以被socket直接调用

接收相关接口recv

#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);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

与send对称的接口

recv也是处理已连接的套接字。

recvfrom通过额外的参数 src_addr与addrlen来获得发送方的地址,addrlen也是输入输出值。

recvmsg与sengmsg相同,把接受的数据都保存在msg中。

都支持设置标志位flags

# Linux 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×