套接字编程简介

IPv4套接字地址结构——网际套接字地址结构

头文件<netinet/in.h>

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 */

}


IPv6套接字地址结构

头文件<netinet/in.h>

struct   in6_addr{

uint8_t s6_addr[16];/* 128-bit IPv6 address, network byte ordered */

}

#define SIN6_LEN/* required for compile-time tests */

struct   sockaddr_in6{

uint8_t sin6_len;/* length of this struct (28) */

sa_family_t sin6_family;/* AF_INET6 */

in_port_t sin6_port;/* transport layer port#, network byte ordered */

unit32_t sin6_flowinfo;/* flow information, undefined */

struct  in6_addr sin6_addr;/* IPv6 address, network byte ordered */

uint32_t sin6_scope_id;/* set of interfaces for a scope */

}

注意 :如果系统支持套接字地址结构中的长度字段,那么SIN6_LEN常值必须定义


字节排序函数

小端:将低序字节存储在起始地址

大端:将高序字节存储在起始地址

主机字节序:某个给定系统所用的字节序


当今有不少系统能够在系统复位时(如MIPS 2000),或者在运行时(例如Intel i860)在大小端之间切换。


主机字节序和网络字节序之间的相互转换:

#include <netinet/in.h>


//主机字节序转网络字节序

uint16_t  htons(uint16_t  host16bitvalue);

uint32_t  htonl(uint32_t  host32bitvalue);


//网络字节序转主机字节序

uint16_t  ntohs(uint16_t  net16bitvalue);

uint32_t  ntohl(uint32_t  net32bitvalue);


在那些与网际协议所用字节序(大端)相同的系统中,这四个函数通常被定义为空宏。



字节操纵函数

4.2BSD Berkeley

#include <strings.h>

void  bzero(void  *dest,  size_t  nbytes);

void  bcopy(const void  *src,  void  *dest,  size_t  nbytes);

int  bcmp(const void  *ptr1,  const void  *ptr2,  size_t  nbytes);


ANSI C

void *memset(void  *dest,  int  c,  size_t  len);

void *memcpy(void  *dest,  const void  *src,  size_t  nbytes);

int  memcpy(const void  *ptr1,  const void  *ptr2,  size_t  nbytes);


memcpy与bcopy类似,不过两个指针参数的顺序相反,当源字节串与目的字节串重叠时,bcopy能够正常处理,但memcpy操作结果却不可知,这种情况必须改用ANSI C的memmove函数。



地址转换函数——在ASCII字符串(人们偏爱使用的格式 192.168.0.1)与网络字节序的二进制值(存放在套接字地址结构中的值 0xC 0xA8 0x0 0x1)之间转换网际地址

#include <arpa/inet.h>

//将字符串转换成32位的网络字节序二进制值,成功返回1,否则返回0

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


//进行相同的转换,只是返回值为32位的网络字节序二进制值,出错时返回INADDR_NONE常值(通常是32位均为1的值),因此255.255.255.255不能由该函数处理

//还有一个问题,有些手册声明该函数出错时返回-1而不是INADDR_NONE,这样该函数的返回值和-1进行比较时可能会发生问题,具体取决于C编译器

//如今已经被废弃。新的代码应该使用inet_aton函数,更好的办法是使用新函数inet_pton(兼容IPv4和IPv6)

in_addr_t  inet_addr(const char  *strptr);


//将32位的网络字节序二进制ipv4地址转换成相应的点分十进制串,返回指向点分十进制数串的指针

//返回值所指向的字符串驻留在静态内存中,这意味着函数不可重入,另外要注意参数是一个结构体

char  *inet_ntoa(struct  in_addr  inaddr);


IPv6出现后新的兼容性转换函数

//函数名字p和n分别代表 表达(presentation) 和 数值(numeric)

#include <arpa/inet.h>

//返回,若成功则为1,若输入不是有效的格式则为0,若出错则为-1

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


//返回:若成功则为指向结果的指针,若出错则为NULL

//如果len太小,不足以容纳表达式格式结果(包括结尾的空字符),那么返回一个空指针,置errno为ENOSPC

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


这两个函数的family参数既可以是AF_INET,也可以是AF_INET6,如果以不被支持的地址族作为family参数,这两个函数都返回一个错误,errno置为EAFNOSUPPORT。


#define  INET_ADDRSTRLEN  16 /* for ipv4 dotted-decimal */

#define INET6_ADDRSTRLEN  46  /* for ipv6 hex string */


TCP套接字为应用进程提供了一个字节流,它们没有记录标记,从TCP套接字read的返回值可能比我们请求的数量少,但是这不表示发生了错误(改进后的readn,writen和readline函数可解决此问题,实现见3.9节)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值