地址族和数据序列

  端口号由16位构成,可分配的端口号范围是0-65535。但0-1023是知名端口,一般分配给特定应用程序。虽然端口号不能重复,但TCP套接字和UDP套接字不会共用端口,所以允许重复。例如:如果某TCP套接字使用9190号端口,则其他TCP套接字就无法使用该端口号,但UDP套接字可以使用。

地址信息的表示

  应用程序中使用的IP地址和端口号以结构体的形式给出了定义,结构体作为地址信息传递给bind函数。

struct sockaddr_in{
    sa_family_t sin_family; //地址族(Address Family)
    uint16_t    sin_port;  //16位TCP/UDP端口号
    struct in_addr   sin_addr; //32位IP地址
    char      sin_zero[8];  //不使用
};

该结构体中提到的另一个结构体in_addr定义如下,它用来存放32位IP地址

struct in_addr{
    In_addr_t  s_addr;  //32位IPv4
};

uint16_t、in_addr_t等类型可以参考POSIX(Portable Operating System Interface,可移植操作系统接口)。POSIX是为UNIX系列操作系统设立的标准

成员sin_family

 成员sin_port

  以网络字节序保存16位端口号

 成员sin_addr

 以网络字节序保存32位IP地址信息

成员sin_zero

  无特殊含义,只是为使结构体sockaddr_in的大小与sockaddr结构体保持一致而插入的成员,必须填充为0。

struct sockaddr_in serv_addr;
//...
if(bind(serv_sock,(struct sockaddr *) &serv_addr,sizeof(serv_addr))==-1)
//...

直接向sockaddr结构体填充信息会带来麻烦

struct sockaddr{
    sa_family_t sin_family;  //地址族
    char sa_data[14];  //地址信息
};

  结构体sockaddr并非只为IPV4设计,这从保存地址信息的数组sa_data长度为14字节可看出。因此,结构体sockaddr要求在sin_family中指定地址族信息。为了与sockaddr保持一致,sockaddr_in结构体中也有地址族信息。

网络字节序与地址变换

大端序:高位字节存放到低位地址

小端序:高位字节存放到高位地址

  通过网络传输数据时约定统一方式,这种约定称为网络字节序——统一为大端序。 

 字节序转换

  在填充sockadr_in结构体前将数据转换成网络字节序。转换字节序的函数如下:

unsigned short htons(unsigned  short);
unsigned short ntohs(unsigned short);
unsigned long  htonl(unsigned long);
unsigned long ntohl(unsigned long);

  htons中的h代表主机(host)字节序,n代表网络字节序。

除了向sockaddr_in结构体填充数据外,其他情况无需考虑字节序问题。(自动转换)

网络地址的初始化与分配

   inet_aton函数与inet_addr函数在功能上完全相同,也将字符串形式IP地址转换为32位网络字节序整数并返回。

  inet_ntoa函数将网络字节序整数型IP地址转换成我们熟悉的字符串形式

网络地址初始化

指定ip地址的初始化:

    struct sockaddr_in addr;
    char* serv_ip = "211.217.168.13";//声明IP地址字符串
    char* serv_port="9190"; //声明端口号字符串
    memset(&addr,0,sizeof(addr)); //结构体变量addr的所有成员初始化为0
    addr.sin_family = AF_INET; // 指定地址族
    addr.sin_addr.s_addr = inet_addr(serv_ip); //基于字符串IP地址初始化
    addr.sin_port = htons(atoi(serv_port));  //基于字符串的端口初始化
//int atoi(const char *str) 把参数 str 所指向的字符串转换为int型
    struct sockaddr_in addr;
    char* serv_port="9190"; //声明端口号字符串
    memset(&addr,0,sizeof(addr)); //结构体变量addr的所有成员初始化为0
    addr.sin_family = AF_INET; // 指定地址族
    addr.sin_addr.s_addr = inet_addr(INADDR_ANY); //基于字符串IP地址初始化
    addr.sin_port = htons(atoi(serv_port));  //基于字符串的端口初始化

  使用常数INADDR_ANY分配服务器端的IP地址,可以自动获取运行服务器端的计算机IP地址,而且,若同一计算机中已分配多个IP地址,则只要端口号一致,就可以从不同IP地址接收数据。

向套接字分配网络地址

 当函数调用成功时,将第二个参数指定的地址信息分配给第一个参数中的相应套接字。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值