您的位置:首页 > 编程语言

socket编程--socket基本概念

2015-08-08 15:49 246 查看
socket

socket可以看成是用户进程与内核网络协议栈的编程接口,不仅可以用于本机的进程间通信,也可以用于网络上不同主机的进程间通信—而管道只能在同一台主机进行通信

应用层依靠socket进行数据传输,我们不必关心底层的内核,即底层数据的传输细节,只关心套接口的存在。

可以把套接口看成进程间的通信,主机A上的进程通过套接口传输数据到主机B的进程。

IPv4套接字地址结构

struct sockaddr_in{
uint8_t sin_len;  /*length of the structure*/
sa_family_t sin_family;  /*AF_INET*/
in_port_t sin_port;     /*16bits TCP or UDP port number*/
struct in_addr sin_addr;
char sin_zeor[8];   /*unused*/
};


说明:sin_len:整个sockaddr_in结构体的长度

sin_family:指定该地址家族,在这里必须设为AF_INET – IPv4

sin_port:端口

sin_addr:IPv4地址

sin_zero:暂不使用,一般将其设为0

其中,结构体in_addr:

struct in_addr {
in_addr_t s_addr;
};


结构体in_addr用来表示一个32位的IPv4地址–字节序为网络字节序

通用地址结构

通用地址结构用来指定与套接字关联的地址

struct sockaddr{
uint8_t sin_len;
sa_family_t sin_family;  /*AF_INET*/
char da_data[14];
};


说明:sin_len:整个sockaddr结构体的长度

sin_family:指定该地址家族

sa_data:由sin_family决定它的形式

可看到:通用地址结构中的da_data有14个字节和IPv4 sin_port(2字节)、sin_addr(4字节)、sin_zero(8字节)相同,说明这两个兼容,通常,进行TCP/IP编程时跟多的是填充IPv4套接口地址结构,然后强制转换为通用地址结构。

网络字节序

字节序

1、大端字节序(Big EndIan)

最高有效位存储在最低内存地址处,最低有效位存储在最高内存地址处

2、小端字节序(Little EndIan)

最高有效位存储在最高内存地址处,最低有效位存储在最低内存地址处

主机主机序

不同主机有不同的字节序,如x86位小端字节序,Motorola 6900为大端字节序,ARM字节序为可配置的

网络字节序

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



为什么要引入字节序这个概念?

socket能够实现异构系统间通信,不同系统字节序不同,引入字节序可实现异构系统通信

测试主机大小端:

int main()

{

unsigned int x = 0x12345678;

unsigned char p = (unsigned char )&x;

printf(“%0x %0x %0x %0x”, p[0],p[1],p[2],p[3]);

return 0;

}



高地址存高内存地址—小端字节序

字节序转换函数

uint32_t htonl(uint32_t hostlong); //将4个字节的主机字节序转换为网络字节序

uint32_t htons(uint32_t hostshort);//2个字节的主机字节序转换为网络字节序

uint32_t ntohl(uint32_t netlong); //相反

uint32_t ntohs(uint32_t netshort);

说明:h代表host;n代表network

s代表short;l代表long

int main()
{
unsigned int x = 0x12345678;
unsigned char *p = (unsigned char *)&x;
printf("%0x %0x %0x %0x\n", p[0],p[1],p[2],p[3]);

unsigned int y = htonl(x);
p = (unsigned char*)&y;
printf("%0x %0x %0x %0x\n", p[0], p[1], p[2], p[3]);
return 0;
}




主机字节序转换为了网络字节序(大端字节序)

地址转换函数

in_addr_t inet_addr (const char *cp);

inet_addr将一个点分十进制IP地址字符串转换成32位数字表示的IP地址(网络字节顺序)。

char* inet_ntoa (struct in_addr in);

inet_ntoa将一个32位数字表示的IP地址转换成点分十进制IP地址字符串。

这两个函数互为反函数

unsigned char *ip = “192.168.1.120”;

int int_ip = inet_addr(ip);

printf(“%d\n”, int_ip);

struct in_addr ipaddr ;
ipaddr.s_addr = int_ip;
printf("%s\n", inet_ntoa(ipaddr));


套接字类型

(1)流式套接字 SOCK_STREAM — TCP

提供面向连接、可靠的数据传输服务,数据按字节流、按顺序收发,保证在传输过程中无丢失、无冗余。TCP协议支持该套接字。

(2)数据报套接字 SOCK_DGRAM – UDP

提供面向无连接的服务,数据收发无序,不能保证数据的准确到达。UDP协议支持该套接字。

(3)原始套接字 SOCK_RAW

允许对低于传输层的协议或物理网络直接访问,例如可以接收和发送ICMP报文。常用于检测新的协议。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: