创建socket
UNIX/Linux的一个哲学:所有的东西都是文件,socket也不例外,可读。可写,可控制,可关闭的文件描述符。
socket基础API在sys/socket.h
下面的socket系统调用可以创建一个socket。
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,int type, int protocol);
参数分析:
也就是说需要指定协议族,使用的协议族下的具体的协议,该具体协议下的具体协议。返回文件描述符。
命名socket
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd,const sockaddr* my_addr,socklen_t addrlen);
也就是说,当创建一个描述符的时候需要将描述符绑定到一个指定的socket地址空间也就是对应的IP的端口号指定的一个进程。
客户端通常不需要命名socket采用的是匿名方式,操作系统自动分配的socket地址(客户端使用的就是这个分配的一个随机的非知名端口号)。
监听socket
socket被命名之后还不能马上接受客户的连接,需要创建一个监听队列存放待处理的客户连接。
服务器通过listen调用被动的接连接。
#include <sys/socket.h>
int listen(int sockfd, int backlog);
为指定的socket设置监听队列,设置队列的长度。
接受连接
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd,struct sockaddr *addr, socklen *addrlen);
accept调用对于客户端的网络断开毫不知情。只是从监听队列当中取出连接,不论连接处于何种状态。
发起连接
客户端通过connect调用主动的与服务器建立连接。
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);
将需要连接的socket地址和创建的socket描述符关联,之后就可通过该描述符与服务器通信。
关闭连接
#include <unistd.h>
int close(int fd);
fd是待关闭的socket的描述符,将fd的引用计数减一只有当引用计数为0的时候才真正的关闭连接。一次fock将是的父进程当中打开的socket引用计数加一。因此必须都关闭才会真正的将连接关闭。
#include <sys/socket.h>
int shutdown(int sockfd,int howto);
showdown调用立即终止连接。
数据读写
- 对文件的读写操作read和write同样适用于socket。
- 同时socket编程接口也提供几个专门的数据读写的系统调用,增加对数据的读写控制。
TCP 数据读写
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd,void *buf,size_t len,int flags);
ssize_t send(int sockfd,const void *buf,size_t len,int flags);
socket的描述符对应一个打开的文件,可以往文件里写入或者读取文件的数据。但是使用其专门的读写接口更加的合适同时可以设定缓冲区提高读写的效率。
UDP数据读写