linux服务器开发-网络编程-套接字
一. socket套接字
1.1 网络字节序
#include <arpa/inet.h>
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。
示例如下:
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
unsigned char buf[sizeof(struct in6_addr)];
int domain, s;
char str[INET6_ADDRSTRLEN];
if (argc != 3) {
fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
exit(EXIT_FAILURE);
}
domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
(strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
s = inet_pton(domain, argv[2], buf);
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
if (inet_ntop(domain, buf, str, INET6_ADDRSTRLEN) == NULL) {
perror("inet_ntop");
exit(EXIT_FAILURE);
}
printf("%s\n", str);
exit(EXIT_SUCCESS);
}
1.2 socket函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
af:一个地址描述。仅支持AF_INET格式,也就是说ARPA Internet地址格式。
type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_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函数
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd,int backlog);
sockfd:socket文件描述符
backlog:排队建立3次握手队列和刚刚建立3次握手队列的连接数和
查看系统默认backlog
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个链接,如果有大量的客户端发起链接而服务器来不及处理,尚未accept的客户端就处于链接等待状态,listen()声明sockfd处于监听状态,并且最多允许有backlog个客户端处于链接等待状态,如果接受到更多的连接请求就忽略,listen()成功返回0,失败返回-1.
1.5 accept函数
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
sockfd:文件描述符
addr:传输参数,返回连接客户端地址信息,含IP地址和端口号
addrlen:传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小
返回值:成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno。
三方握手成功后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来,addr是一个传出参数,accept()返回时传出客户端的地址和端口号,addrlen参数是一个传入传出参数,传入的是调用者提供的缓冲区addr的长度以避免缓冲区出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区),如果给addr参数传null,表示不关心客户端的地址。
1.6 connect函数
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket文件描述符
addr:传入参数,指定服务器端地址信息,含IP地址和端口号
addrlen:传入参数,传入sizeof(addr)大小
返回值:成功返回0,失败返回-1,设置errno
客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址,connect()成功返回0,出错返回-1.
还没有评论,来说两句吧...