socket函数
int socket(int domain, int type, int protocol); //返回:若成功则返回非负描述符,失败返回-1
1)调用socket函数创建套接字
2)domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET(IPv4)、AF_INET6(IPv6)等
3)type:指定socket类型。常用的socket类型有,SOCK_STREAM(流式套接字)、SOCK_RAW(原始套接字)等
4)protocol:就是指定协议。常用的协议有,IPPROTO_IP(IP协议)、IPPROTO_TCP(TCP传输协议)、PPTOTO_UDP(UDP传输协议)等
5)type和protocol不可以随意组合,protocol为0时,会自动选择type类型对应的默认协议
6)返回一个唯一标识的套接字描述符
bind函数
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //返回:若成功则返回0,失败返回-1
1)将套接字绑定到某个地址struct上,struct包含IP、端口号等
listen函数
int listen(int sockfd, int backlog); //返回:若成功则返回0,失败返回-1
1)服务器在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求;backlog:可以排队的最大连接个数
2)socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求
connect函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //返回:若成功则返回0,失败返回-1
1)客户端通过调用connect函数来建立与TCP服务器的连接,第二参数为服务器的socket地址
accept函数
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //返回:若成功则返回非负描述符,失败返回-1
1)服务器依次调用socket()、bind()、listen()之后,就会监听指定的socket了;客户端依次调用socket()、connect()之后就向服务器发送一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数去接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作
2)accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听套接字描述符;而accept函数返回的是已连接的套接字描述符;一个服务器通常通常仅仅只创建一个监听套接字,它在该服务器的生命周期内一直存在;为每个连接的客户端连接创建一个已连接套接字,当服务器完成了对某个客户的服务,相应的已连接套接字就被关闭
read函数和write函数
ssize_t read(int fd, void *buf, size_t nbytes); ssize_t write(int fd, const void *buf, size_t nbytes);
1)read函数是负责从文件描述符fd中读取内容到buf,nbytes为buf的大小,当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了
2)write函数将buf中的nbytes字节内容写入fd,成功时返回写的字节数,返回值通常与nbytes的值相同
close函数
int close(int sockfd); //返回:若成功则返回0,失败返回-1
1)close一个套接字的默认行为是关闭套接字,然后此套接字描述符就不能再被调用进程使用了,如果有数据残留在发送缓冲区中,系统将试着把这些数据发送给对端
2)在多进程并发服务器模型中,父子进程共享套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,引用计数会相应的减1,当引用计数仍大于0时,这将不会触发FIN的发送