不同主机间的通信问题
实现网络通信
网络编程
Open System Interconnect (OSI网络模型)
为了解决不同体系结构的网络的互联问题,国际标准化组织ISO(注意不要与OSI搞混)于1981年制定了开放系统互连参考模型
(Open System Interconnection Reference Model,OSI/RM)
7. 应用层 | 直接获取要收发的数据 |
6. 表示层 | 规定了 传输数据的格式 和 方式 //加密 |
5. 会话层 | 处理一次会话过程 |
4. 传输层 | 传输控制层,控制传输过程,保证数据完整和可靠 |
3. 网络层 (网际层) | 用于解决 网络 与 网络之间 数据传输 //数据包 |
2. 数据链路层 | 规定了传输数据的格式 //帧数据 控制传输过程可靠 |
1. 物理层 | 规定了物理层面的电气特性及相关机械特性 物理层面数据的传输 --- 一位一位二进制数据 //比特流 |
实际应用到的是 tcp/ip 模型 ;每个层次中,都有自己的一套规范 (协议)
(1)用户层 应用层 ---------程序员
(2)内核层 传输层----------这些层次 操作系统已经实现
网络层 //tcp/ip 协议 栈 (网络协议栈)
数据链路层
物理层
是网络中主机的唯一标识,它由网络地址和主机号组成。网络地址是子网的唯一标识,类似于电话号码的区号;主机号是子网内每台主机的编号。在现在(IPv4)的网络中,IP地址是32bit的二进制数,采用大端字节序:
直接使用二进制数,不容易记忆,为了方便记忆,将32位二进制码划分为4个字节,每个字节转化成相应的十进制数,字节之间用“.”来分隔,这种表示方法,称之为“点分十进制表示法”。
例:192 .168 .1 .1
11000000 10101000 00000001 00000001
类型 |
范围 |
用途 |
|
A类 |
0.x.x.x---127.x.x.x.x |
10.x.x.x |
私网(局域网)地址 |
127.x.x.x |
环回网络地址 |
||
其他 |
大型主干网地址 |
||
B类 |
128.x.x.x - 191.x.x.x |
172.16.x.x - 172.31.x.x |
私网(局域网)地址 |
169.254.x.x |
表示没有找到DHCP服务器 |
||
其他 |
主干(城市)网地址 |
||
C类 |
192.x.x.x - 223.x.x.x |
192.168.x.x |
私网(局域网)地址 |
D类 |
组播地址 |
||
E类 |
保留 |
注意:主机号为0的IP地址是网络地址,主机号为255的地址是广播地址。
网络号 + 主机号
用来表示主机中某一个具体(进行网络通信)进程 ;16位数值(unsigned short ) //0~65535 (65536个数)标示一个进程
ip+端口:进程在网络的 地址
TCP和 UDP 的端口号是独立的
端口号一般由IANA (Internet Assigned NumbersAuthority) 管理
1)众所周知端口:
1~1023(1~255之间为众所周知端口,256~1023端口通常由UNIX系统占用)
知名端口号(已经分配给标准应用服务软件)
如:
http协议用到的端口号 80
2) 已登记端口:
1024~49151
注册端口号(非标准应用服务软件的软件可以申请的端口号范围)
3)动态或私有端口://50000 以上的端口号
49152~65535 动态分配的端口号(系统动态分配给应用程序使用的)
2字节(16bit)
mask // 遮住 (255.255.255.0)
获取IP地址中的网络地址和主机地址:
一种面向连接的传输层协议,它能提供高可靠性通信(即数据无误、数据无丢失、数据无失序、数据无重复到达的通信)
用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。
编程模型
c/s client server 客户端,服务器模型 --- 专用客户端
b/s browser server 浏览器,服务器模型 --- 通用的客户端
p2p peer to peer 点对点传输
(1)client ---客户端 --- 角色 --- 主动的角色
socket:
sendto :发数据
(2)server --- 服务器端 --角色 --- 被动的角色
socket :
recvfrom //接收数据
int socket(int domain, int type, int protocol);
(1)功能:程序向内核提出创建一个基于内存的套接字描述符
(2)参数:domain:域 (范围) ---socket 用于什么范围的通信,ipv4 / ipv6 ;
domain 地址族, PF_INET == AF_INET ==>互联网程序
PF_UNIX == AF_UNIX ==>单机程序
type :套接字类型:
protocol 协议 ==》0 表示自动适应应用层协议。
(3)返回值:成功:返回申请的套接字文件描述符 ;失败: -1
#include
#include /* See NOTES */
#include
int main(int argc, const char *argv[])
{
int fd = socket(AF_INET,SOCK_DGRAM,0);
if (fd < 0)
{
perror("socket fail");
return -1;
}
printf("fd = %d\n",fd);
return 0;
}
ssize_t sendto( int sockfd, //用于通信的socket对应的fd
const void *buf, //表示要发送的数据所在的一块空间
size_t len, //表示发送的字节数
int flags, //0 --- 默认const struct sockaddr *dest_addr, //表示 要发送到的 地址 (网络地址 ip+端口号 )
socklen_t addrlen); //表示dest_addr 这个参数的长度
返回值:成功发送出去的字节的数 ;失败: -1 ;
#include
#include /* See NOTES */
#include
#include
#include /* superset of previous */
#include
#include
int main(int argc, const char *argv[])
{
int fd = socket(AF_INET,SOCK_DGRAM,0);
if (fd < 0)
{
perror("socket fail");
return -1;
}
printf("fd = %d\n",fd);
char buf[1024] = "hello udp\n";
struct sockaddr_in seraddr;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(50000);
seraddr.sin_addr.s_addr = inet_addr("192.168.1.149");
sendto(fd,buf,strlen(buf)+1,0,(const struct sockaddr *)&seraddr,sizeof(seraddr));
return 0;
}
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address IP */
};/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};