[关闭]
@zwh8800 2017-08-23T10:05:09.000000Z 字数 3272 阅读 192250

unix网络编程中常用头文件、结构体、函数

blog 归档 unix 网络编程 笔记


unix网络编程中常用头文件、结构体、函数


1.常用头文件

<sys/socket.h>

socket, bind, connect等函数定义, 所有socket程序必须要包含, 另外定义了一些通用的套接字地址结构, 如struct sockaddr.

<netinet/in.h>

struct sockaddr_in, struct sockaddr_in6等结构体的定义, 定义了ip协议中的套接字地址结构. 另外有些基础类型定义in_addr_t, in_port定义. hton*, ntoh* 字节序转换函数.

<arpa/inet.h>

inet_pton, inet_ntop, ip地址转换函数.

2.部分函数原型与结构体定义

1)ipv4套接字地址结构体定义:

  1. /* from <netinet/in.h> */
  2. /* Internet address. */
  3. typedef uint32_t in_addr_t;
  4. struct in_addr
  5. {
  6. in_addr_t s_addr;
  7. };
  8. /* Structure describing an Internet socket address. */
  9. struct sockaddr_in
  10. {
  11. __SOCKADDR_COMMON (sin_);
  12. in_port_t sin_port; /* Port number. */
  13. struct in_addr sin_addr; /* Internet address. */
  14. /* Pad to size of `struct sockaddr'. */
  15. unsigned char sin_zero[sizeof (struct sockaddr) -
  16. __SOCKADDR_COMMON_SIZE -
  17. sizeof (in_port_t) -
  18. sizeof (struct in_addr)];
  19. };

《unix网络编程》上的定义:

  1. struct in_addr {
  2. in_addr_t s_addr;
  3. };
  4. struct sockaddr_in {
  5. uint8_t sin_len;
  6. sa_family_t sin_family;
  7. in_port_t sin_port;
  8. struct in_addr sin_addr;
  9. char sin_zero[8];
  10. };

2)POSIX规范定义的类型:

image_1bl0dmjqfum819j74jn19na1ecv9.png-77.2kB

3)通用的套接字地址:

  1. struct sockaddr {
  2. uint_8 sa_len;
  3. sa_family_t sa_family;
  4. char sa_data[14];
  5. };

4)各种套接字地址结构体:

image_1bl0dnjs71238jhiqo21omc17s5m.png-187.3kB

5)字节序函数:

  1. #include <netinet/in.h>
  2. uint32_t htonl(uint32_t hostlong);
  3. uint16_t htons(uint16_t hostshort);
  4. uint32_t ntohl(uint32_t netlong);
  5. uint16_t ntohs(uint16_t netshort);

6)ip地址转换函数:

  1. #include <sys/types.h>
  2. #include <sys/socket.h>;
  3. #include <arpa/inet.h>
  4. int inet_pton(int af, const char *src, void *dst);
  5. const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);

这两个函数传入(或传出)的ip地址结构体为struct in_addr等结构体

传出的字符串buffer大小在中定义:

  1. #define INET_ADDRSTRLEN 16
  2. #define INET6_ADDRSTRLEN 48

7)套接字函数:

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. int socket(int domain, int type, int protocol);
  4. int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
  5. int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
  6. int listen(int s, int backlog);
  7. int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
  8. int getsockname(int s, struct sockaddr *name, socklen_t *namelen);
  9. int getpeername(int s, struct sockaddr *name, socklen_t *namelen);

3.常见用法

1)初始化套结字地址结构:

对于IPV4一般需要初始化三个字段:sin_family、sin_addr、sin_port。

  1. bzero(&svraddr, sizeof(svraddr));/* 注意清零 */
  2. svraddr.sin_family = AF_INET;
  3. svraddr.sin_port = htons(PORT);/* 注意大端小端的转换 */
  4. svraddr.sin_addr.s_addr = htonl(INADDR_ANY);/* 设置ip地址为任意地址 */
  5. if (inet_pton(AF_INET, "192.168.0.1", &addr.sin_addr) < 0)/* 使用inet_pton设置ip */
  6. {
  7. perror("inet_pton");
  8. exit(errno);
  9. }

2)创建套结字:

  1. svrsock = socket(AF_INET, SOCK_STREAM, 0);/* 参数3可以推断得出 */
  2. if (svrsock == -1)
  3. {
  4. perror("socket");
  5. exit(errno);
  6. }

3)绑定套结字到套结字地址:

  1. if (bind(svrsock, (SA*)&svraddr, sizeof(svraddr)) == -1)
  2. {
  3. perror("bind");
  4. exit(errno);
  5. }

4)连接套结字到对端:

  1. if (connect(svrsock, (SA*)peeraddr, sizeof(peeraddr)) == -1)
  2. {
  3. perror("connect");
  4. exit(errno);
  5. }

5)设置套结字为监听模式:

  1. if (listen(svrsock, 64) == -1)
  2. {
  3. perror("listen");
  4. exit(errno);
  5. }

6)从套结字上等待一个连接:

  1. int cltsock;
  2. struct sockaddr_in cltaddr;
  3. socklen_t cltaddrlen = sizeof(cltaddr);
  4. if ((cltsock = accept(svrsock, &cltaddr, &cltaddrlen)) == -1)
  5. {
  6. perror("accept");
  7. exit(errno);
  8. }

7)获取本端和对端套结字地址:

  1. struct sockaddr_in addr;
  2. socklen_t addrlen = sizeof(addr);
  3. if (getsockname(svrsock, &addr, &addrlen) == -1)
  4. {
  5. perror("getsockname");
  6. exit(errno);
  7. }
  8. if (getpeername(svrsock, &addr, &addrlen) == -1)
  9. {
  10. perror("getpeername");
  11. exit(errno);
  12. }

8)将ip地址转换为字符串形式

  1. char cltaddrstr[INET_ADDRSTRLEN];
  2. if (inet_ntop(AF_INET, &cltaddr.sin_addr, cltaddrstr, INET_ADDRSTRLEN) == NULL)/* 注意为cltaddr.sin.addr */
  3. {
  4. perror("inet_ntop");
  5. exit(errno);
  6. }

9)将字符串转成ip地址

  1. if (inet_pton(AF_INET, "192.168.1.1", &cltaddr.sin_addr) == -1)
  2. {
  3. perror("inet_pton");
  4. exit(errno);
  5. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注