Socket:看成用户进程与内核网络协议栈的编程接口。 Socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机的进程间通信。
(不同主机可能经过路由器,路由器工作在IP层(网络层))
不同进程间通信,是一种全双工的模式,可以在不同体系架构的进程间通信(比如手机上的CPU是ARM,PC机上的是X86系统架构),软件平台可以不一样,硬件平台也可以不一样。
地址属性: 上述地址是: sockaddr_in
sin_family:IPV4是AF_INET。由于socket不仅仅支持TCP/IP,还支持Unix域协议编程,不同协议,地址结构形式可能不一样。 sin_port是16位,2个字节,和sin_addr是4个字节。
所以有通用地址结构 :
sockaddr
大端:Big Endian 最高有效位存储在最低内存地址处,最低有效位存在在最高内存地址处。 小端:little Endian 最高有效位存储在最高内存地址处。
网络字节序:是大端字节序。
主机A和主机B通信,两个主机如果不是同一种形式的字节序,就需要转换。不同主机之间,可能有不同的字节序,如 x86为小端字节序,Motorola 6800为大端字节序,ARM字节序是可配置的。
#include<iostream> #include <winsock.h> #pragma comment(lib, "ws2_32") //http://bbs.csdn.net/topics/190038207 //#include <winsock.h> //包含winsock这个头文件,内容是网络编程socket相关部分API //#pragma comment(lib,"Ws2_32.lib") //这是链接API相关连的Ws2_32.lib静态库 using namespace std; int main() { unsigned int A = 0x12345678;//0x开头,是以16进制表示,0开头是8进制,没有的是10进制 //注意对A的理解,因为FF是1111 1111,一个字节。所以0x12345678是可以用四个字节的int表示的,没问题。 //unsigned int可以表示最大的数是:4294967295,40多个亿。 cout << sizeof(A) << endl;//sizeof表示一个int占用字节数,和A的实际值无关。 unsigned char *p = (unsigned char *)&A;//取A的地址,在内存中占用4个字节(其实内存中每个字节占用的位置都有一个边号,这就是地址) //这里需要注意的是,A的地址的值是存放到p指针指向的那块地址处,那块地址存的内容是A的地址,但那块地址的值和A没关系 int addr_p = (int)p; cout <<hex<<addr_p << endl; //这个输出的是p的地址,然后对p的地址进行int强制转换,并以十六进制输出 cout << hex << *(int *)addr_p << endl; //画个图就明白了 for (int i = 0; i < 4;i++) cout <<hex<<(int)p[i]; //78 56 43 12 最高有效位12存在p[4],即内存的高有效位,属于小端存储 cout << endl; //printf("%0x_%0x_%0x_%0x", p[0], p[1], p[2], p[3]); unsigned long y = htonl(A);//转换成网络字节序 p = (unsigned char *)&y; for (int i = 0; i < 4; i++) cout << hex << (int)p[i]; cout << endl; //测试地址转换函数 对192.168.0.100,它对应的32位整数是什么样的? //in_addr_t inet_addr(const char *cp),将点分十进制转化为32位整数 unsigned long addr = inet_addr("192.168.0.100"); unsigned long addr_oct = ntohl(addr); cout <<oct<< addr_oct << endl; //这里不指明oct,默认会以hex输出,因为在上面的cout中已经指出了hex格式输出了 struct in_addr ipaddr; //char *addr_p = inet_ntoa(struct in_addr in); 将 /*memcpy(&ipaddr, &addr_oct, 4);*/ ipaddr.S_un.S_addr = 30052000144;//30052000144是网络字节序转换的结果,是大端模式,所以肯定不是原来的IP地址对应的32位整数了。 cout << inet_ntoa(ipaddr) << endl; ipaddr.S_un.S_addr = inet_addr("192.168.0.100"); char *sss = inet_ntoa(ipaddr); cout << sss << endl; return 0; }流式套接字:SOCK_STREAM 提供无面向连接的,可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收。
数据报式套接字:SOCK_DGRAM 提供无连接服务。不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
原始套接字:SOCK_RAW 直接将应用层封装成IP层认识的数据格式。
