accept函数_基础套接字函数入门1
想不想自己写一个简单的QQ?想不想自己写一个聊天室?想不想知道2000年的人是如何上网的?本节讲解一些基础的网络函数,带你看看,编写一个完整的TCP客户端、服务端需要掌握哪些函数?之后,我们要开发自己的QQ。
1 socket函数
// sys/socket.h /* 使用协议__protocol在域__domain中创建一个__type类型的新套接字。 如果__protocol为零,则自动选择一个。 返回新套接字的文件描述符,或者返回-1表示错误。 */ extern int socket (int __domain, int __type, int __protocol) __THROW;- __domain:即family,AF_INETIPv4协议,AF_INET6IPv6协议
- __type:SOCK_STREAM字节流套接字,SOCK_DGRAM数据报套接字,SOCK_RAW原始套接字
- __protocol:IPPROTO_TCPTCP传输协议,IPPROTO_UDPUDP传输协议
socket函数在成功时返回一个小的非负整数值,它与文件描述符类似,我们把它称为套接字描述符(socket descriptor),简称socketfd。
AF_前缀表示地址族,PF_前缀表示协议族 ,因为历史上曾想让一个协议族(PF)支持多个地址族(AF),用PF来创建套接字,用AF来创建套接字地址结构,然而就只是想想,没有实现。现在AF和PF的值是相等的。
// bits/socket.h /* Protocol families. */ #define PF_INET 2 /* IP protocol family. */ #define PF_INET6 10 /* IP version 6. */ /* Address families. */ #define AF_INET PF_INET #define AF_INET6 PF_INET62 connect函数
// sys/socket.h #define __CONST_SOCKADDR_ARG const struct sockaddr * extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);- __fd:socket函数返回的套接字描述符
- __addr:指向套接字结构地址的指针
- __len:该套接字的大小
TCP客户用connect函数和TCP服务器建立连接。客户在调用connect函数前可以不调用bind函数,因为如果有需要,内核会确定本机IP地址,并选择一个临时端口作为源端口。
3 bind函数
// sys/socket.h /* 把一个本地协议地址赋值给一个套接字 */ #define __CONST_SOCKADDR_ARG const struct sockaddr * extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) __THROW;- 对于IPv4来说,协议地址是32位的IPv4地址和16位的端口号组合。
- 对于IPv6来说,协议地址是128位的IPv6地址和16位的端口号组合。
绑定操作涉及3个对象:套接字,地址和端口。其中套接字是捆绑的主体,地址和端口是捆绑的客体。在套接字上绑定地址和端口表示:该地址和端口已经被套接字使用。
- 如果指定端口号为0,那么内核在bind被调用的时候选择一个临时端口。
- 如果指定IP地址是通配地址,那么内核将等到套接字已连接(TCP)或在套接字上发出数据报(UDP)时才选择一个本地IP地址。
对于IPv4来说,通配地址是0(INADDR_ANY),如果让内核帮套接字选择一个端口,那么必须注意,bind函数并不返回所选择的端口号。因为bind函数的_addr参数有const限定词,它无法返回所选的值。为了拿到内核选择的临时端口,必须调用getsockname函数来返回协议地址。
4 listen函数
// sys/socket.h extern int listen (int __fd, int __n) __THROW;listen函数仅有TCP服务器调用,它做两件事:
- 未完成连接队列:每个处于三次握手中的TCP连接,套接字处于SYN_RCVD状态。
- 已完成连接队列:每个已完成三次握手的TCP连接,套接字处于ESTABLISHED状态。
这2个队列之和不能超过__n,否则就无法新建TCP连接,这就是SYN Flood攻击的原理。
5 accept函数
// sys/socket.h extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len);accept函数由TCP服务器调用,用于从已完成连接队列的队头返回下一个已完成连接。如果该队列为空,那么进程被投入睡眠。(默认套接字为阻塞方式)
参数__addr和__addr_len返回已连接的对端进程的协议地址,即返回客户端的协议地址。__addr_len是值-结果参数,返回内核存放在协议地址中实际的字节数。如果对客户端的协议地址不感兴趣,可以将指针置为NULL。
注意:如果accept成功,返回值是又内核自动生成的全新描述符,称为已连接套接字。服务端与客户通信,将用这个套接字,服务完成后,这个套接字就被关闭。 而参数__fd称为监听套接字, 一个服务仅仅创建一个监听套接字。6 close函数
// /usr/include/unistd.h extern int close (int __fd);close函数一般可以用来关闭套接字,并终止TCP连接。但是在并发服务器中,close函数仅仅将套接字描述符引用计数减1。所以并不能一定在TCP连接上发送FIN报文,如果想在TCP连接上发送FIN报文,可以用shutdown函数。
参考文献:《UNIX网络编程 卷1:套接字联网API》
总结
以上是生活随笔为你收集整理的accept函数_基础套接字函数入门1的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: python pypdf2另存为图片_用
- 下一篇: excel 复制数据 sql serve