linux服务器开发-网络编程-套接字

╰+哭是因爲堅強的太久メ 2023-10-06 19:48 66阅读 0赞

一. socket套接字
1.1 网络字节序

  1. #include <arpa/inet.h>
  2. int inet_pton(int af, const char *src, void *dst);

inet_pton:将“点分十进制” -> “二进制整数”
int inet_pton(int af, const char src, void dst);
这个函数转换字符串到网络地址,第一个参数af是地址簇,第二个参数src是来源地址,第三个参数
dst接收转换后的数据。
inet_pton 是inet_addr的扩展,支持的多地址族有下列:
af = AF_INET
src为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址转换为in_addr的结构体,并复制在dst中。
af = AF_INET6
src为指向IPV6的地址,函数将该地址转换为in6_addr的结构体,并复制在
dst中。
如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0。
示例如下:

  1. #include <arpa/inet.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. int
  6. main(int argc, char *argv[])
  7. {
  8. unsigned char buf[sizeof(struct in6_addr)];
  9. int domain, s;
  10. char str[INET6_ADDRSTRLEN];
  11. if (argc != 3) {
  12. fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
  13. exit(EXIT_FAILURE);
  14. }
  15. domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
  16. (strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
  17. s = inet_pton(domain, argv[2], buf);
  18. if (s <= 0) {
  19. if (s == 0)
  20. fprintf(stderr, "Not in presentation format");
  21. else
  22. perror("inet_pton");
  23. exit(EXIT_FAILURE);
  24. }
  25. if (inet_ntop(domain, buf, str, INET6_ADDRSTRLEN) == NULL) {
  26. perror("inet_ntop");
  27. exit(EXIT_FAILURE);
  28. }
  29. printf("%s\n", str);
  30. exit(EXIT_SUCCESS);
  31. }

1.2 socket函数

  1. #include <sys/types.h> /* See NOTES */
  2. #include <sys/socket.h>
  3. int socket(int domain, int type, int protocol);
  4. af:一个地址描述。仅支持AF_INET格式,也就是说ARPA Internet地址格式。
  5. type:指定socket类型。新套接口的类型描述类型,如TCPSOCK_STREAM)和UDPSOCK_DGRAM)。常用的socket类型有,SOCK_STREAMSOCK_DGRAMSOCK_RAWSOCK_PACKETSOCK_SEQPACKET等等。
  6. protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCPIPPROTO_UDPIPPROTO_STCPIPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

1.3 bind函数
#include
#include
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket文件描述符
addr:构造出IP地址加端口号
addrlen:sizeof(addr)长度
返回值:成功返回0,失败返回-1,设置errno。

1.4 listen函数

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. int listen(int sockfd,int backlog);
  4. sockfd:socket文件描述符
  5. backlog:排队建立3次握手队列和刚刚建立3次握手队列的连接数和

查看系统默认backlog
cat /proc/sys/net/ipv4/tcp_max_syn_backlog

典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个链接,如果有大量的客户端发起链接而服务器来不及处理,尚未accept的客户端就处于链接等待状态,listen()声明sockfd处于监听状态,并且最多允许有backlog个客户端处于链接等待状态,如果接受到更多的连接请求就忽略,listen()成功返回0,失败返回-1.

1.5 accept函数

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
  4. sockfd:文件描述符
  5. addr:传输参数,返回连接客户端地址信息,含IP地址和端口号
  6. addrlen:传入传出参数(值-结果),传入sizeofaddr)大小,函数返回时返回真正接收到地址结构体的大小
  7. 返回值:成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

三方握手成功后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来,addr是一个传出参数,accept()返回时传出客户端的地址和端口号,addrlen参数是一个传入传出参数,传入的是调用者提供的缓冲区addr的长度以避免缓冲区出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区),如果给addr参数传null,表示不关心客户端的地址。

1.6 connect函数

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
  4. sockfd:socket文件描述符
  5. addr:传入参数,指定服务器端地址信息,含IP地址和端口号
  6. addrlen:传入参数,传入sizeof(addr)大小
  7. 返回值:成功返回0,失败返回-1,设置errno

客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址,connect()成功返回0,出错返回-1.

发表评论

表情:
评论列表 (有 0 条评论,66人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Linux网络编程(中)

    ✨ ⭐️ ? ?我们将TCP服务器封装成一个类,当我们定义出一个服务器对象后需要马上对服务器进行初始化,而初始化TCP服务器要做的第一件事就是创建套接字。TCP服务器在调...