1.网络通信概念:不同主机进程间通信
1.国际网络体系结构:
OSI模型: open system interconnect 理论模型
。
应用层:要传输的数据信息,如文件传输,电子邮件等
表示层:数据加密,解密操作,压缩,解压缩
会话层:建立数据传输通道
传输层:传输的方式 UDP TCP 端口号
网络层:实现数据路由 路由器 ip
数据链路层:封装成帧,点对点通信(局域网内通信),差错检测 交换机 ARP
物理层:定义物理设备标准,比如网线,光纤等传输介质 比特流传输 ( 0 1)
TCP/IP模型: 工业模型
4层
应用层:HTTP、HTTPS(超文本传输协议基于tcp)、FTP(文件传输协议,基于TCP)、TFTP(简单文件传输协议,基于udp)、MQTT(物联网),
DNS(域名解析服务,域名变ip) www.baidu.com------------------》IP
传输层: UDP : 用户数据报协议 面向数据包
TCP:传输控制协议 面向数据流
网络层:IPv4,ipv6
网络接口层:网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路
5层
应用层:HTTP、HTTPS、FTP、TFTP、MQTT
传输层:TCP、UDP
网络层:IP
数据链路层:封装成帧,点对点通信(局域网内通信),差错检测 交换机
物理层:定义物理设备标准,比如网线,光纤等传输介质 比特流 bit
2.协议相关概念
**应用层协议**:
见上
传输层协议:
UDP:用户数据报协议
TCP:传输控制协议
**网络层**:
windows上:查看ip地址:ipconfig
ifconfig: 查看虚拟机的IP地址
IP协议
192.168.1.128
IPv4 32位
IPv6 128位
192.168.1.3 (用户表示形式) 点分十进制
11000000101010000000000100000011 (计算机存储形式) 32bits
IP地址 = 网络位 + 主机位
192.168.0.121/24
24:网络位的位数
网络位:该IP地址位于哪个网段(局域网)内
主机位:这个网段(局域网)第几台主机
**子网掩码**(通过子网掩码去辨别主机位和网络位):
如:255.255.255.0
11111111.11111111.11111111.00000000
用来区分IP地址的网络位和主机位,搭配IP地址使用。
子网掩码是1的部分对应IP地址的网络位
子网掩码是0的部分对应IP地址的主机位
**网段号**:
IP地址网络位不变,主机位全为0,则为该IP地址的网段号
网段内的IP能直接通信
**广播号**:
IP地址网络位不变,主机位全为1,则为该IP地址的广播号
广播号:
192.168.1.255(向广播号发送信息,所有局域网内IP都能收到此信息)
IP地址的划分:
(1)A类地址:
范围:1.0.0.0 - 126.255.255.255
子网掩码:255.0.0.0 126*2^24
用于管理大规模网络
私有IP地址:10.0.0.0 - 10.255.255.255
127.0.0.0 回环地址
(2)B类地址:
范围:128.0.0.0 - 191.255.255.255
子网掩码:255.255.0.0 2^16
管理大中规模网络
私有IP地址:172.16.0.0 - 172.31.255.255
(3)C类地址:
范围:192.0.0.0 - 223.255.255.255
子网掩码:255.255.255.0 2^8
管理中小规模网络
私有IP地址:192.168.0.0 - 192.168.255.255
(4)D类地址:
224.0.0.0 - 239.255.255.255
组播和广播使用
(5)E类地址:
240.0.0.0 - 255.255.255.254
用来进行实验
公有IP:由电信公司直接分配,并需要付费的IP地址, 可以直接访问internet
私有IP:不能直接访问internet的ip地址
节省ip地址
端口号: 16位的数值 0-65535
作用:唯一的标识一个进程
每一个应用进程都有一个端口号;
通讯时用来区分数据包属于哪一个进程。
分类:
1)任何TCP/IP实现所提供的服务都用1-1023之间的端口号。
http : 80
FTP: 20/21
TFPT: 69
HTTPS: 443
2)端口号从1024-49151是被注册的端口号,被IANA指定为特殊服务使用。
3)从49152-65535是动态或私有端口号。
IP+PORT : 可以找到目标主机上的目标进程
2. udp
框架
server:socket() 以及ser的初始化===>bind()=>recvfrom()=>close()
client:socket() =>初始化接收方(ser)=>sendto() ===>close()
网络编程之 UDP
UDP:用户数据报协议
1、特性:
1.发送数据时不需要建立链接,节省资源开销
2.不安全不可靠的协议(尽最大努力交付),可能存在丢包和乱序的问题 //一般用在实时性比较高的广播,组播//vnc:允许数据丢失(视频画面传输,游戏,直播). 实时性高
3.面向数据包。
4.资源开销小
2、框架:
C/S模式 :有一个专用的客户端 client----server
QQ1--->腾讯服务器
B/S模式 :有一个通用的客户端浏览器
browser----server
套接字编程接口:
1.socket
套接字:通信对象的抽象, 网络通信的端口,一个通信链的句柄。
int socket(int domain, int type, int protocol);
功能:
创建一个用来通信的接口(文件描述符)
参数:
domain:通信的协议族(AF_INET:IPv4协议族)
type:
SOCK_DGRAM:数据报套接字 (UDP使用此类型)
SOCK_STEAM:流式套接字 (TCP使用此类型)
SOCK_RAW:原始套接字
protocol:
默认传0 按照协议的默认属性创建
返回值:
成功返回用来进行通信的文件描述符
失败返回-1
2.sendto
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
向一个IP地址和端口发送数据信息
端口号:区分一台主机不同的应用程序(0 - 65535)
参数:
sockfd:套接字文件描述符
buf:发送数据空间首地址
len:发送数据的长度
flags:发送数据属性(默认为0)
dest_addr:目的IP地址和端口
addrlen:目的IP地址和端口的长度
返回值:
成功返回实际发送字节数
失败返回-1
struct sockaddr 通用地址类型
struct sockaddr_in IPv4地址类型(使用时需要强转)
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 */
};
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
3.htons----》主机转网络
主机:小端 host
网络:大端 network
uint32_t htonl(uint32_t hostlong); 主机转网络
uint16_t htons(uint16_t hostshort); 主机转网络
uint32_t ntohl(uint32_t netlong); 网络转主机
uint16_t ntohs(uint16_t netshort); 网络转主机
h:host
n:net
l:long
s:short
4.inet_addr
in_addr_t inet_addr(const char *cp);
功能:
将字符串IP地址转换成二进制IP地址形式
char *inet_ntoa(struct in_addr in);
功能:
将二进制ip转换成字符串
练习:
循环从终端接收字符串,并发送给串口调试助手,
5.bind(一般用在服务端)
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:将一个套接字与IP地址和端口号绑定(只能绑定自己的IP地址)
参数:
sockfd:套接字文件描述符
addr:IP地址和端口号结构体首地址
addrlen:长度
返回值:
成功返回0
失败返回-1
6.recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:
接收网络发送的数据信息
参数:
sockfd:套接字文件描述符
buf:存放数据空间首地址
len:最大能够接收的数据个数
flags:属性默认为0
src_addr:存放发送端IP地址信息的空间首地址
addrlen:想要接收的数据长度的空间首地址
返回值:
成功返回实际接收字节数
失败返回-1
具有阻塞功能(直到接收到数据,才会继续向下执行)
3.练习
1.1. 利用UDP实现一个文件发送(注意有可能丢包,发送方加个延迟就不会了)
**客户端**
# include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
perror("fail socket");
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.164");//接收方ip转换为二进制ip
int fd = open("2.jpg",O_RDONLY);
off_t len =lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
printf("len = %d",len);
char buff[1024];
ssize_t size = sendto(sockfd,&len,4,0,(struct sockaddr *)&ser,sizeof(ser));//发送文件大小
size_t ret = read(fd,buff,sizeof(buff));//读文件
int num = 0;
while( ret>0)
{
printf("ret = %ld\n",ret);
ssize_t size = sendto(sockfd,buff,ret,0,(struct sockaddr *)&ser,sizeof(ser));//发送给服务端
// sleep(1);
num = num +size;
memset(buff , 0,sizeof(buff));//clear buff!
ret = read(fd,buff,sizeof(buff));
//`sleep(1);
}
}
**服务端**
# include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
perror("fail socket");
return -1;
}
struct sockaddr_in cil;
socklen_t cillen = sizeof(cil);
struct sockaddr_in ser;
ser .sin_family = AF_INET;
ser.sin_port = htons(50000);//主机转网络
ser.sin_addr.s_addr = inet_addr("192.168.0.164");//ip字符串转二进制
int len = 0;
int ret = bind (sockfd ,(struct sockaddr *)&ser, sizeof(ser));
if(ret <0)
{
perror("fail bind");
return -1;
}
char buff[1024] = {0};
recvfrom(sockfd,&len,4,0,(struct sockaddr *)&cil,&cillen);//注意时长度的地址
size_t size = recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr *)&cil,&cillen);//自动获得cil相关信息,如果不需要信息则可以写两个NULL
size_t num =size;
int fd = open("3.jpg",O_WRONLY | O_CREAT| O_TRUNC,0664);
printf("len = %d\n",len);
while(num <= len)
{
write(fd,buff,size);
memset(buff ,0,sizeof(buff));
size = recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr *)&cil,&cillen);//自动获得cil相关信息
num = num +size;
}
}
注意fwrite,fread有可能丢最后一次数据 ,最后一次读不到想要的数据大小就返回0最后一次就没读到(慎用)
标签:udp,addr,int,34,buff,IP地址,include,day,struct From: https://blog.csdn.net/qq_53671628/article/details/144964346