Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1468774
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: LINUX

2012-05-17 16:26:25

Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} socket地址结构(定长)

struct sockaddr_in {

   short int sin_family; /* 通信类型 */

   unsigned short int sin_port; /* 端口 */

   struct in_addr sin_addr; /* Internet 地址 */

   unsigned char sin_zero[8]; /* sockaddr结构的长度相同*/

   };

 

struct in_addr {

unsigned long s_addr; // 32 IP 地址,网络字节序

};

 

注意 sin_zero (它被加入到这个结构,并且长度和 struct sockaddr 一样应该使用函数 bzero()  memset() 来全部置零。 同时,这一重要的字节,一个指向 sockaddr_in结构体的指针也可以被指向结构体sockaddr并且代替它。这 样的话即使 socket() 想要的是 struct sockaddr *,你仍然可以使用 struct sockaddr_in,并且在最后转换。

sin_port sin_addr 必须是网络字节顺序 (Network Byte Order)

socket 地址结构(定长)

struct in6_addr{

uint8_t s6_addr[16]; //128 IP 地址,网络字节序

}

struct sockaddr_in6{

uint8_t sin6_len; //IPv6 为固定的24 字节长度

sa_family_t sin6_family; //地址簇类型,为AF_INET6

in_port_t sin6_port; //16 位端口号,网络字节序

uint32_t sin6_flowinfo; //32 位流标签

struct in6_addr sin6_addr; //128 IP 地址

}

socket 地址结构

struct sockaddr {

     uint8_t sa_len;

   unsigned short sa_family; /* 地址家族, AF_xxx */

   char sa_data[14]; /*14字节协议地址*/

   };

sa_family 能够是各种各样的类型,但是在这篇文章中都是 "AF_INET"

 

--------------------------------------------------------------------------------

一个16位整数,它由2个字节组成。

内存中存储这两个字节有两种方法:

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

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

 

网际协议必须指定一个网络字节序(Network Byte Order)

 

主机字节序和网络字节序的转换函数:

#include

unit16_t htons(uint16_t host16bitvalue);

unit32_t htonl(uint32_t host32bitvalue);

unit16_t ntohs(uint16_t net16bitvalue);

unit32_t ntohl(uint32_t net32bitvalue); 

 

h : host 

n : network

s : short (16 bits)

l : long (32 bits) 

 

--------------------------------------------------------------------------------

#include

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

inet_aton函数将strptr 所指的C字符串转换成32位的网络字节序二进制值并通过指针addrptr来存储。如果成功返回1,否则返回0

 

in_addr_t inet_addr(const char *strptr);

inet_addr函数将strptr 所指的C字符串转换成32位的网络字节序二进制值并通过涵数值返回。若成功,返回32位二进制的网络字节序地址;若出错,则返回INADDR_NONE

假设已经有了一个sockaddr_in结构体ina,有一个IP "132.241.5.10"要储存在其中,可以使用函数inet_addr()IP地址从点分格式转换成无符号长整型。使用方法如下:

ina.sin_addr.s_addr = inet_addr("132.241.5.10");

注意,inet_addr()返回的地址已经是网络字节格式,所以你无需再调用函数htonl()

 

char *inet_ntoa (struct in_addr inaddr);

函数inet_ntoa将一个32位的网络字节序二进制IPv4地址转换成相应的点分十进制数串。

返回:指向点分十进制数串指针 

将一个in_addr结构体输出成点分格式的IP地址,使用函数inet_ntoa()("ntoa"的含义是"network to ascii"),如:

printf("%s",inet_ntoa(ina.sin_addr));

它将输出IP地址。需要注意的是inet_ntoa()将结构体in_addr作为一个参数,不是长整形。同样需要注意的是它返回的是一个指向一个字符的指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址。例如:

char *a1, *a2;

……

……

a1 = inet_ntoa(ina1.sin_addr); /* 这是198.92.129.1 */

a2 = inet_ntoa(ina2.sin_addr); /* 这是132.241.5.10 */

printf("address 1: %s\n",a1);

printf("address 2: %s\n",a2);

输出如下:

address 1: 132.241.5.10

address 2: 132.241.5.10

假如你需要保存这个IP地址,使用strcopy()函数来指向你自己的字符指针。

 

-------------------------------------------------------------

 

字节流处理函数

void bzero(void *s, int n); //置字节字符串s的前n个字节为零

 

void bcopy(const void *src, void *dest, int n); //将字符串src的前n个字节复制到dest

 

int bcmp(const void *s1, const void *s2, int n); //比较字符串s1s2的前n个字节是否相等

返回:0——相等,非0——不相等

 

void *memset(void *buffer, int c, int count);  //buffer所指内存区域的前count个字节设置成字符c

 

 

void *memcpy(void *dest, void *src, unsigned int count);  //src所指内存区域复制count个字节到dest所指内存区域

 

int memcmp(void *buf1, void *buf2, unsigned int count); //比较内存区域buf1buf2的前count个字节。

返回:0——相同,非0——不相同

 

字节流读写函数

 

ssize_t readn(int filedes, void * buff, size_t nbytes);

 

ssize_t writen(int filedes, const void *buff, size_t nbytes);

 

ssize_t readline(intfiledes, void *buff, size_t maxlen);

 

--------------------------------------------------------------------------------

 

TCP/IPsocket提供下列三种类型套接字。 

 

1)字节流套接字(SOCK_STREAM 

提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。 

 

2)数据报套接字(SOCK_DGRAM 

提供了一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。 

 

3)原始套接字(SOCK_RAW 

该接口允许对较低层协议,如IPICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。 

 

定义一个连接的一个端点的两元组,即IP 地址和端口号,称为一个套接口

 

在网络连接中,两个端点所组成的四元组(即本地IP、本地PORT、远程IP 和远程PORT

称为socket pair,该四元组唯一的标识了一个网络连接。该情况可通过netstat 证。

阅读(717) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~