只记录API关键信息方便快速回忆。API的具体信息还请man。以前初学的时候记录的信息太冗杂了。现在看也不方便看,这回力求精简,痛苦的重写一遍概要。
socket API
server
- 最基本API使用流程
1
2
3
4
5
6
7
8
9
10
11
12
13// 1. create socket
int lfd = socket(PF_INET,SOCK_STREAM,0);
// 2. bind socket with addr
// 之前要先将protocol、ip、port以网络字节序存储入server_addr
bind(lfd,(sockaddr*)&server_addr,sizeof server_addr);
// 3. listen
listen(lfd,5);
// 4. accept
int connfd = accept(fd,(sockaddr*)&cliet_addr,&len);
// 5. read/write
int len = read(fd,buf,BUFFER_SIZE-1);
// 6. close
close(fd);socket地址
- sockaddr_in :
1
2
3
4
5
6
7
8
9
10struct sockaddr_in
{
sa_family sin_family; // protocol :AF_INET
u_int16_t sin_port; // port :网络字节序
struct in_addr sin_addr; // ip :IPv4结构体
};
struct in_addr
{
u_int32_t s_addr; // ip address : 网络字节序
}- 将 port(short) 和 ip(点分十进制字符串) 以网络字节序保存,供给socket使用。
- 程序员看到的 port 是 : 本地字节序 && short。看到的ip是 本地字节序 && 点分十进制字符串。
- 将他们以网络字节序存入sockaddr_in
1
2
3
4
5
6// 将protocol、ip、port以网络字节序存储入server_addr
struct sockaddr_in server_addr;
memset(&server_addr,0,sizeof server_addr);
server_addr.sin_family = AF_INET; // protocol network
inet_pton(AF_INET,ip,&server_addr.sin_addr.s_addr); // ip str->network
server_addr.sin_port = htons(port); // port network
- 将 port(short) 和 ip(点分十进制字符串) 以网络字节序保存,供给socket使用。
socket
- 原型
- int socket(int domain,int type,int protocol);
- return fd;
- 使用
- int listening_fd = socket(PF_INET,SOCK_STREAM,0);
bind
- 原型:
- int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
- 将socket地址addr结构体,绑定给sockfd。
- 使用:
- bind(listening_fd,(sockaddr*)&server_addr,sizeof server_addr);
listen
原型
- int listen(int sockfd, int backlog);
- 创建监听队列以存放待处理客户连接
使用
- listen(listening_fd,5);
在listen之后listening_fd即变为监听socket,可以接受连接/epoll了。
accept
- 原型
- int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- success : return connection fd;
- fail : return -1 and set errno
- 使用
- int connfd = accept(lfd,(sockaddr*)&cliet_addr,&cliet_len);
- accept之后即可对connfd进行读写操作
- 即便client建立连接之后又断开网络或者退出程序,server也可连接
- accept只是从监听队列中取出连接,而不论连接处于何种状态。
client
client socketAPI流程
1
2
3
4
5
6
7
8
9// 1. 创建socket
int client_conn_fd = socket(PF_INET, SOCK_STREAM, 0);
// 2. 发起连接
// 之前要将要连接的server的protocol、ip、port以网络字节序存储入server_addr
connect(client_conn_fd, (sockaddr *)&server_address, sizeof server_address);
// 3. read/write
send(client_conn_fd, request.c_str(), request.size(), 0);
// 4. close
close(client_conn_fd);connect
原型
- int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
- success : return 0
- fail : return -1 and set errno
使用
- connect(client_fd, (sockaddr *)&server_address, sizeof server_address);