linux网络编程之Socket

本文介绍了Linux网络编程中涉及的Socket结构,包括`sockaddr_in`和`sockaddr_in6`,以及字节序的概念,如大端字节序、小端字节序和网络字节序。还提到了字节序转换函数`htonl`、`htons`、`ntohl`和`ntohs`。此外,文章讨论了不同类型的Socket,如流式套接字(SOCK_STREAM)、数据报式套接字(SOCK_DGRAM)和原始套接字(SOCK_RAW)。

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

一.socket
socket可看作是用户进程与内核网络协议的编程接口.
socket可用于本机进程间的通信,也可用于网络上不同主机间的进程通信.

下图显示的是各种网络协议的地址格式:
1.struct socketaddr(通用地址结构)
通过获取某种socketaddr结构体的首地址,不需要知道具体是哪种类型的socketaddr结构体,就可以根据地址类型字段确定结构体的内容. 因此,socket API可以接受各种类型的sockaddr结构体指针做参数,例如bind、accept、connect等函数,这些函数的参数应该设计成void *类型以便接受各种类型的指针,但是sock API的实现早于ANSI C标准化,那时还没有void *类型,因此这些函数的参数都用struct sockaddr *类型表示,即通用地址结构:
struct sockaddr {
               sa_family_t  sin_family;
               char sa_data[14];
}; 
2.struct socketaddr_in(IPv4地址), 包括16位端口号和32位IP地址:

struct sockaddr_in {
               sa_family_t    sin_family;
               in_port_t      sin_port;  
               struct in_addr sin_addr;  

char sin_zero[8]; 
           };

struct in_addr {
               uint32_t       s_addr;    

           };

3.struct sockaddr_in6(IPv6地址),包括16位端口号、128位IP地址和一些控制字段.


在传递参数之前要强制类型转换一下,例如:

struct sockaddr_in servaddr;

 

bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));

linux网络编程之Socket
二.网络字节序

字节序
大端字节序(Big Endian)
最高有效位(MSB:Most Significant Bit)存储于最低内存地址处,最低有效位(LSB:Lowest Significant Bit)存储于最高内存地址处。
小端字节序(Little Endian)
最高有效位(MSB:Most Significant Bit)存储于最高内存地址处,最低有效位(LSB:Lowest Significant Bit)存储于最低内存地址处。
主机字节序
不同的主机有不同的字节序,如x86为小端字节序,Motorola 6800为大端字节序,ARM字节序是可配置的。

网络字节序
网络字节序规定为大端字节序

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。


#include

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);


h表示host,n表示network,l表示32位长整数,s表示16位短整数。例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。


下面程序测试本机是大端机or小端机:

linux网络编程之Socket


本机输出的是小端字节序,经过htonl转换为网络字节序(大端).
linux网络编程之Socket

三.地址转换
socketaddr_in的成员struct in_addr sin_addr表示32位的IP地址.
通过以下函数将字符串转换为结构体表示的地址:

字符串转in_addr的函数:
#include

int inet_aton(const char *strptr, struct in_addr *addrptr);

in_addr_t inet_addr(const char *strptr);

int inet_pton(int family, const char *strptr, void *addrptr);

 

注意,转换而成的32位数是网络字节序的。


in_addr转字符串的函数:

char *inet_ntoa(struct in_addr inaddr);

const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

 

注意,传入的32位数也是网络字节序的。


下面程序演示这两种函数的用法:

linux网络编程之Socket

linux网络编程之Socket

四.socket类型

流式套接字(SOCK_STREAM)
提供面向连接的、可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收。
数据报式套接字(SOCK_DGRAM)
提供无连接服务。不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
原始套接字(SOCK_RAW)


原文请参考: http://blog.csdn.net/jnu_simba/article/details/9012521

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值