C++-后端开发入门-TCP服务器编程
格式转换
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <arpa/inet.h> typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; }; in_addr_t inet_addr(const char* __cp); char* inet_ntoa(struct in_addr __in);
in_addr_t dwIP=inet_addr("172.16.2.6"); struct in_addr ia; ia.s_addr=dwIP; printf("real_ip=%s\n",inet_ntoa(ia));
|
套接字常用结构
⼀个套接字代表通信的⼀端,每端都有⼀个套接字地址,包含了IP地址和端⼝信息。套接字地址分为通用套接字地址和专用套接字地址。
通用套接字地址结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct sockaddr { __SOCKADDR_COMMON(sa_); char sa_data[14]; };
|
该结构过小,如IPv6和UNIX等地址长度超长,且为了内存对齐,Linux采用新的通用套接字地址结构:
1 2 3 4 5 6
| #define __ss_aligntype unsigned long int struct sockaddr_storage { __SOCKADDR_COMMON(ss_); char __ss_padding[_SS_PADSIZE]; __ss_aligntype __ss_align; };
|
Linux为不同协议族定义了不同套接字地址结构体,称为专用地址结构体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
typedef uint16_t in_port_t; typedef uint32_t in_addr_t; struct in_addr{ in_addr_t s_addr; };
struct sockaddr_in { __SOCKADDR_COMMON(sin_); in_port_t sin_port; struct in_addr sin_addr; unsigned char sin_zero[sizeof(struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof(in_port_t) - sizeof(struct in_addr)]; };
struct in6_addr { union { uint8_t __u6_addr8[16]; uint16_t __u6_addr16[8]; uint32_t __u6_addr32[4]; } __in6_u; };
struct sockaddr_in6 { __SOCKADDR_COMMON(sin6_); in_port_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; };
|
当一个套接字绑定了地址,可获取它的套接字地址。套接字通信需要在本地和远程两端建立套接字,所以获取套接字地址分为获取本地套接字地址和获取远程套接字地址。getsockname
可在以下两种情况下获取本地套接字地址,并可用getpeername
获取通信对端套接字地址。
- 本地套接字用
bind
获取地址。
- 本地套接字没有绑定地址,但用
connect
和远程建立了连接,此时内核分配一个地址给本地套接字。
1 2 3 4 5 6 7 8 9 10 11
| #include <sys/socket.h> int getsockname( int sockfd, struct sockaddr* localaddr, socklen_t* addrlen ); int getpeername( int sockfd, struct sockaddr* peeraddr, socklen_t* addrlen );
|
P243