socket编程 sockaddr sockaddr_in

本文介绍了socket编程的基本概念,包括sockaddr_in结构体的定义及其在网络通信中的应用,详细解释了IP地址处理函数inet_addr()、inet_ntoa()等的使用方法,并对比了网络字节顺序与主机字节顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

socket编程 sockaddr sockaddr_in

Windows下与Linux下编写socket程序的区别
http://blog.chinaunix.net/uid-2270658-id-308160.html
sockaddr_in , sockaddr , in_addr区别Socket编程函数集(非常有用)
http://810364804.iteye.com/blog/2094531
ntohs, ntohl, htons,htonl的比较和详解
http://www.360doc.com/content/12/0222/10/54470_188560773.shtml

struct sockaddr和struct sockaddr_in这两个结构体用来处理网络通信的地址。
在各种系统调用或者函数中,只要和网络地址打交道,就得用到这两个结构体。

include <netinet/in.h>
//sockaddr是给操作系统使用
struct sockaddr {
    unsigned short    sa_family;     // 2 bytes address family, AF_xxx,sa_family是地址家族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET,代表TCP/IP协议族
    char              sa_data[14];   // 14 bytes of protocol address
};
// IPv4 AF_INET sockets:
//程序员应使用sockaddr_in来表示地址,sockaddr_in区分了地址和端口
struct sockaddr_in {
    short            sin_family;     // 2 bytes e.g. AF_INET, AF_INET6
    //sockaddr用其余14个字节来表示sa_data, sockaddr_in把14个字节拆分成sin_port, sin_addr和sin_zero
    unsigned short   sin_port;       // 2 bytes e.g. htons(3490), 端口号
    struct in_addr   sin_addr;       // 4 bytes see struct in_addr, below, IP 地址
    char             sin_zero[8];    // 8 bytes zero this if you want to, sin_zero用来填充字节使sockaddr_in和sockaddr保持一样大小
};

struct in_addr {
    unsigned long s_addr;            // 4 bytes load with inet_pton()
};

typedef struct in_addr {
    union {
      struct{ unsigned char  s_b1, s_b2, s_b3, s_b4; } S_un_b;
      struct{ unsigned short s_w1, s_w2; } S_un_w;
      unsigned long S_addr;         //一般用这个(使用网络字节顺序存)
    }S_un;
} IN_ADDR;

IP地址处理:
inet_addr(): –将IP地址从点数格式转换成无符号长整型,函数返回的地址已是网络字节格式, 如:
sockaddr_in ina;
ina.sin_addr.s_addr = inet_addr(“132.241.5.10”);//与调用函数htonl()功能一样,
//代码没有错误检查,当inet_addr()发生错误时返回-1。(无符号数)-1和IP地址255.255.255.255相符合!这是广播地址!所以要先进行错误检查
ina.sin_addr.s_addr = inet_addr(“192.168.0.1”); //是将一个点分制的IP地址(如192.168.0.1)转换为ina.sin_addr.s_addr结构中需要的32位IP地址(0xC0A80001)。
inet_ntoa():–将IP地址从长整型转换成点数格式, 如:
inet_ntoa(ina.sin_addr));
它将输出IP地址。需要注意的是inet_ntoa()将结构体in-addr作为一个参数,不是长整形。
同样需要注意的是它返回的是一个指向一个字符的指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址

BSD网络编程中包含了两个函数,用来在二进制地址格式和点分十进制字符串格式之间相互转换,这两个函数仅仅支持IPv4:
in_addr_t inet_addr(const char *cp);
//将网络地址转成二进制的数字
unsigned long int inet_addr(const char *cp); //将参数cp所指的网络地址字符串转换成网络所使用的二进制数字
//将网络地址转成二进制的数字
int inet_aton(const char* cp, struct in_addr *inp); //将参数cp所指的网络地址字符串转换成网络使用的二进制的数字,然后存于参数inp所指的in_addr结构中
//将二进制的数字转换成网络地址
char* inet_ntoa(struct in_addr in); //将参数in所指的网络二进制的数字转换成网络地址,然后将指向此网络地址字符串的指针返回
功能相似的两个函数(但可同时支持IPv4和IPv6):

const char *inet_ntop(int domain, const void *addr, char *str, socklen_t size);
int inet_pton(int domain, const char *str, void *addr);
如:
char IPdotdec[20];  //存放点分十进制IP地址
192.168.0.1
struct in_addr s;   // IPv4地址结构体  
inet_pton(AF_INET, IPdotdec, (void *)&s); // 
inet_ntop(AF_INET, (void *)&s, IPdotdec, 16);

字节的网络顺序和主机顺序:
网络字节顺序与本地字节顺序之间的转换函数

htonl()--"Host to Network Long int"   32Bytes 
ntohl()--"Network to Host Long int"   32Bytes 
htons()--"Host to Network Short int"  16Bytes 
ntohs()--"Network to Host Short int"  16Bytes 

计算机数据表示存在两种字节顺序:
网络字节顺序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关, 如:
//将32位主机字符顺序转换成网络字符顺序
unsigned long int htonl(unsigned long int hostlong);//将参数指定的32位hostlong转换成网络字符顺序
//将16位主机字符顺序转换成网络字符顺序
unsigned short int htons(unsigned short int hostshort);//将参数指定的16位hostshort转换成网络字符顺序

一般的用法为:
程序员把类型、ip地址、端口填充sockaddr_in结构体,然后强制转换成sockaddr作为参数传递给系统调用函数

网络编程中一段典型的代码为:

int sockfd;
struct sockaddr_in servaddr;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);

// 填充struct sockaddr_in 
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);

// 强制转换成struct sockaddr 
connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值