UNIX网络编程:套接字

一、套接字地址结构

1.The Internet (IPv4) socket address structure:

struct in_addr {
  in_addr_t   s_addr;           /* 32-bit IPv4 address */
                                /* network byte ordered */
};

struct sockaddr_in {
  uint8_t         sin_len;      /* length of structure (16) */
  sa_family_t     sin_family;   /* AF_INET */
  in_port_t       sin_port;     /* 16-bit TCP or UDP port number */
                                /* network byte ordered */
  struct in_addr  sin_addr;     /* 32-bit IPv4 address */
                                /* network byte ordered */
  char            sin_zero[8];  /* unused */
};

2.The generic socket address structure

struct sockaddr {
  uint8_t      sa_len;
  sa_family_t  sa_family;    /* address family: AF_xxx value */
  char         sa_data[14];  /* protocol-specific address */
};

二、值-结果参数

1)从进程到内核传递的套接字地址结构的函数有三个: bind, connect, sendto。这些函数的参数一个是指向某个套接字地址结构的指针,另一个是该结构的整数大小,这样内核就知道到底从进程复制多少数据进来。
这里写图片描述

例如:

struct sockaddr_in serv;

/* fill in serv{} */
connect (sockfd, (SA *) &serv, sizeof(serv));

当函数调用时,结构大小是一个值,它告诉内核该结构的大小,这样内核在写该结构的时候不至于越界。
2)从内核到进程传递套接字地址结构的函数有4个:accept,recvfrom,getsockname,getpeername.

这里写图片描述
例如:

struct sockaddr_un  cli;   /* Unix domain */
socklen_t  len;

len = sizeof(cli);         /* len is a value */
getpeername(unixfd, (SA *) &cli, &len);
/* len may have changed */

当函数返回时,结构大小又是一个结果,它告诉进程:内核在该结构存储了多少信息。

三、字节排序函数

1.大端字节序与小段字节序

这里写图片描述
程序:输出主机字节序

#include     "unp.h"

 int main(int argc, char **argv)
 {
     union {
         short   s;
         char    c[sizeof(short)];
     } un;

     un.s = 0x0102;
     printf("%s: ", CPU_VENDOR_OS);
     if (sizeof(short) == 2) {
         if (un.c[0] == 1 && un.c[1] == 2)
             printf("big-endian\n");
         else if (un.c[0] == 2 && un.c[1] == 1)
             printf("little-endian\n");
         else
             printf("unknown\n");
     } else
         printf("sizeof(short) = %d\n", sizeof(short));

    exit(0);
}

Tips:网际协议使用大端字节序来传送多字节整数。

转换函数

#include <netinet/in.h>

 //均返回网络字节序
uint16_t htons(uint16_t host16bitvalue) ;//16位(端口号)

uint32_t htonl(uint32_t host32bitvalue) ;//32位(IPv4地址)
 //均返回主机字节序

uint16_t ntohs(uint16_t net16bitvalue) ;

uint32_t ntohl(uint32_t net32bitvalue) ;

四、字节操纵函数

当处理套接字地址结构的时候(例如IP地址中某些字段包含值为0的字节,但却不是C字符串),需要一些函数,它们既不对数据做出解释,也不假设数据是以空字符结束的C字符串。

有两组这样的函数

1.源自Berkeley的函数:名字以b开头(表示字节)的一组函数,只有两个参数

#include <strings.h>

void bzero(void *dest, size_t nbytes);  
//把目标字符串中指定数目字节置为0

void bcopy(const void *src, void *dest, size_t nbytes);
//将指定数目的字节从源字符串复制到目标字符串

int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);
//比较两个字符串的指定字节数。

2.源自ANSI C标准,以mem开头(表示内存)

#include <string.h>

void *memset(void *dest, int c, size_t len);
//把目标字符串中指定数目字节置为c

void *memcpy(void *dest, const void *src, size_t nbytes);
//将指定数目的字节从源字符串复制到目标字符串,当源串和目的串重合的时候,结果不可预知。

int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
 //比较两个字符串的指定字节数。

五、地址转换函数

1.在点分十进制字符串与32位网络字节序之间转换

#include <arpa/inet.h>

int inet_aton(const char *strptr, struct in_addr *addrptr);
//字符串转化为字节序,通过addrptr存储,若字符串有效返回1,否则返回0;

in_addr_t inet_addr(const char *strptr);
//字符串转化为网络字节序,若字符串有效,返回32位IPv4地址,否则返回INADDR_NONE错误

char *inet_ntoa(struct in_addr inaddr);
//网络字节序转化为点分十进制字符串指针,该指针所指空间在静态内存中,所以该函数是不可重入的(该函数执行过程中不能中断,不适用与多任务环境,若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。) 

参考可重入函数与不可重入函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值