socket套接字编程
头文件
#include <sys/types.h>
#include <sys/socket.h>
数据结构
涉及的结构体struct sockaddr_in与struct sockaddr
sockaddr_in 和 sockaddr 是并列的结构(占用的空间是一样的),指向 sockaddr_in 的结构体的指针也可以指向 sockadd 的结构体,并代替它,而且sockaddr_in 结构对用户将更加友好,在使用的时候进行类型转换就可以了。
struct socketaddr_in{
sa_family_t sin_family; //定义了网络接口协议类型
in_port_t sin_port; //定义了端口号
struct in_addr sin_addr; //存储转换后的地址
}
struct in_addr{
uint32_t s_addr; //address in network byte order
}
函数
socket
用于创建套接字,并指定相关参数
int socket(int _domin, int _type, int _protocol);
参数
_domin
用于指定一个通信域,来选择协议族。
一般使用AF_INET
,AF_INET6
,分别表示ipv4以及ipv6。
_type
用来指定套接字类型
经常使用的是
SOCK_STREAM
以及SOCK_GDRAM
_protocol
用来为给定的通信域和套接字类型选择默认协议
通常情况下,SOCK_STREAM
默认为tcp协议,SOCK_GDRAM
默认为udp协议
返回值
当调用成功时,回返回一个int socket描述符,当不需要时,可以使用close(int socket_fd)
来关闭它。
当调用失败时,会返回一个-1的值,同时会设置 errno 变量以指示错误类型。
使用示例
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket");
exit(EXIT_FAILUER);
}
bind
用于给套接字绑定一个ip或者端口号
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
参数
sockfd
指定要绑定的套接字socket描述符
addr
是一个指向用以存储相关数据的数据结构struct sockaddr的指针,一般使用
struct sockaddr*
对
取地址的struct sockaddr_in
进行转换
addrlen
指示addr的长度
返回值
成功返回 0,失败情况下返回-1,并设置 errno 以提示错误原因。
使用示例
if(bind(sockfd, (struct sockaddr*)&saddr, sizeof(sock)){
perror("bind");
exit(EXIT_FAILURE);
}
listen
只能在服务器进程中使用,让服务器进程进入监听状态,等待客户端的连接请求。一般在bind
之后accept
之前使用
int listen(int sockfd, int backlog)
参数
sockfd
指定socket描述符
backlog
用来描述 sockfd 的等待连接队列能够达到的最大值。在服务器处理客户端请求时,如果有其他客户端请求连接,就会将这些请求放入一个队列中,
backlog
则规定了这个队列的上限。
返回值
成功返回0,失败返回-1
使用示例
if(listen(sockfd, backlog)){
perror("listen");
exit(EXIT_FAILURE);
}
accept
用来获取客户端的连接请求并建立连接
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
参数
sockfd
指定作用的socket套接字
*addr
用来返回已连接的客户端的 IP 地址与端口号等这些信息
*addrlen
设置为 addr 所指向的对象的字节长度
如果对客户端ip和端口号这些信息不感兴趣,可以将后两个设置为NULL
返回值
成功返回新的文件描述符
失败返回-1
使用示例
int nsockfd = accept(sockfd, &addr, &addrlen);
if(nsockfd == -1){
perror("accept");
exit(EXIT_FAILURE);
}
connect
用于客户端,客户端调用此函数将套接字 sockfd 与远程服务器进行连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数
sockfd
指定与服务器建立连接的套接字
*addr
指定了待连接的服务器的 IP 地址以及端口号等信息
addrlen
指定了待连接的服务器的 IP 地址以及端口号等信息
返回值
成功则返回 0
失败返回-1,并设置 errno 以指示错误原因
read/write
使用时可以从套接字描述符中读取或者向其中写入数据
返回值
成功返回读取/写入的字节数,但如果读取时小于设定读取的字节数,并不意味错误
失败返回-1
recv
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数
*buf
接收缓冲区
len
接收字节数(缓冲区长度)
flag
接收数据控制标志
- MSG_CMSG_CLOEXEC 为UNIX域套接字上接收的文件描述符设置执行时关闭标志
- MSG_DONTWAIT 启动非阻塞操作(相当于O_NONBLOCK)
- MSG_ERRQUEUE 接收错误信息作为辅助数据
- MSG_OOB 如果协议支持,接收带外数据
- MSG_PEEK 返回数据包内容而不真正取走数据包(瞄一眼)
- MSG_TRUNC (即使数据包被截断,也返回数据包的长度)
- MSG_WAITALL 等待直到所有的数据可用,即接收数据量达到指定的字节数
一般来说,会将flags设置为0。
返回值
成功返回接收数据大小 >0
另一端关闭套接字 0
错误返回-1,并设置errno
使用示例
if(recv(sockfd, buf, len, 0) < 0){
perror("recv");
exit(EXIT_FAILURE);
}
send
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数
与recv相似
flags
发送数据控制标志
- MSG_CONFIRM 提供链路层反馈以保持地址映射有效
- MSG_DONTROUTE 不要将数据包路由出本地网络
- MSG_DONTWAIT 允许非阻塞操作
- MSG_EOR 如果协议允许,标志记录结束
- MSG_MORE 延迟发送数据包允许写更多数据
- MSG_NOSIGNAL 在写无连接套接字时不产生SIGPIPE信号
- MSG_OOB 如果协议支持,发送带外数据
返回值
成功返回发送字节数
失败返回-1
close
用于关闭套接字