IP地址的分类:
A 类 0.0.0.0 到 127.255.255.255
B 类 128.0.0.0 到 191.255.255.255
C 类 192.0.0.0 到 223.255.255.255
D 类 224.0.0.0 到 239.255.255.255
E 类 240.0.0.0 到 247.255.255.255
0 IP不可用
1 IP一般用做路由的网关 (不可用)
255 IP是用来做该网段的广播地址 (不可用的)
C类的可以用主机号为: 2 - 254
网络的分层模型:
OSI七层模型:
应用层
表示层
会话层-》应用层
传输层
网络层
数据链路层
物理层 -》物理层
TCP/IP的4层模型:
应用层
传输层
网络层
物理层
传输层:TCP 协议 UDP 协议
TCP协议:TCP传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。 (传输速度慢,网络会阻塞,用于控制指令,与文件的传输,每次数据的交互都以一个字节为单位的)
UDP协议:UDP数据报协议,是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,(传输速度快,网络不会阻塞,只会丢失数据,多用于多媒体数据传输(视频,音频等))
TCP搭建流程:
客户端:创建socket、连接服务器connect、进行通信(read/write/recv/send)、关闭通信close
服务器端:创建socket、绑定socket(bind)、设置为监听模式listen、接收客户端的连接请求accpt、进行通信、关闭通信。
在客户端和服务器端连接时会发生三次握手即客户端发送连接请求后,服务器回馈一个信号,然后才连接完成。
UDP搭建流程:
客户端:穿件socket、接收或发送(recvfrom/sendto)、关闭通信
服务器端:创建socket、绑定socket、接收或发送、关闭通信。
下面是代码的编写
TCP客户端:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
//sockaddr_in结构体
/*
struct sockaddr_in {
__kernel_sa_family_t sin_family; //协议族
__be16 sin_port; //端口号
struct in_addr sin_addr; //IP地址
*/
int main()
{
//1.创建TCP通信对象
int socketfd=socket(AF_INET,SOCK_STREAM,0);
if(socketfd < 0)
{
perror("creat sock fail\n");
return -1;
}
else
{
printf("creat ok\n");
}
//初始化服务的地址信息
struct sockaddr_in seraddr={0};
seraddr.sin_family = AF_INET; //使用IPv4协议
seraddr.sin_port = htons(6666); //网络通信都使用大端格式
seraddr.sin_addr.s_addr = inet_addr("x.x.x.x"); //32位的整形
//链接服务器 struct sockaddr *
int ret=connect(socketfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
if(ret != 0)
{
perror("connect fail\n");
}
else
{
printf("connect ok\n");
}
//接收信息
while(1)
{
char buf[1024]={0};
scanf("%s",buf);
write(socketfd,buf,strlen(buf)); //不断接收网络信息到buf中
if(strcmp(buf,"exit") == 0)
{
break;
}
printf("buf=%s\n",buf);
}
//关闭网络通信
close(socketfd);
}
TCP服务器端
int main()
{
//1.创建TCP通信对象
int socketfd=socket(AF_INET,SOCK_STREAM,0);
if(socketfd < 0)
{
perror("creat sock fail\n");
return -1;
}
else
{
printf("creat ok\n");
}
//2.进行IP地址的绑定 bind
struct sockaddr_in seraddr={0};
seraddr.sin_family = AF_INET; //指定网络协议为 IPV4
seraddr.sin_port = htons(6666); //取值范围 最大值65535 16位的整形 1024以后
seraddr.sin_addr.s_addr = INADDR_ANY; //自动检测IP地址
int ret=bind(socketfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret != 0)
{
perror("bind fail\n");
return -1;
}
else
{
printf("bind ok\n");
}
//设置为监听模式
ret=listen(socketfd,5); //5是最大监听数backlog
if(ret != 0)
{
perror("listen fail\n");
return -1;
}
else
{
printf("listen ok\n");
}
//接受对方的链接请求
struct sockaddr_in clienaddr={0};
int len=0;
int newsocket=0;
while(1)
{
printf("等待客户端链接\n");
newsocket=accept(socketfd,(struct sockaddr *)&clienaddr,&len);
if(newsocket < 0)
{
perror("accept fail\n");
return -1;
}
else
{
printf("accept ok\n");
//输出对方的IP地址信息
printf("newsocket=%d,clien:ip:%s,clien:port:%d\n",newsocket,inet_ntoa(clienaddr.sin_addr),ntohs(clienaddr.sin_port));
break; //跳出循环
}
}
//进行通信
while(1)
{
char buf[1024]={0};
read(newsocket,buf,sizeof(buf));
printf("buf=%s\n",buf);
}
}
UDP有三种模式:单播、广播和组播
单播即为指定对象进行通信,因为UDP没有客户端和服务器端的区别,因此写代码时需要绑定ip和端口;
广播地址一般是在该网段的xxx.xxx.xxx.255,可以向在该网段的所有人发送消息数据;
组播需要用到组播地址(224.0.0.0到239.255.255.255),加入到该组播地址的所有人可接受到信息。
单播
int main(int argc,char *argv[])
{
//创建UDP通信协议
socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd < 0 )
{
perror("creat socket fail\n");
return -1;
}
//设置UDP的地址并绑定
struct sockaddr_in seraddr={0};
seraddr.sin_family = AF_INET; //使用IPv4协议
seraddr.sin_port = htons(atoi(argv[1]));
seraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
int ret = bind(socketfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret < 0)
{
perror("bind fail:");
return -1;
}
pthread_t tid=0;
pthread_create(&tid,NULL,func,NULL);
//数据的接收
while(1)
{
char buf[1024]={0};
struct sockaddr_in seraddr1={0}; //保持发送者的IP地址信息
int len=0;
recvfrom(socketfd,buf,1024,0,(struct sockaddr*)&seraddr1,&len);
printf("buf = %s\n",buf);
}
}
组播
int main(int arg, char * args[])
{
//1.创建UDP socket
int st = socket(AF_INET, SOCK_DGRAM, 0);
if (st == -1)
{
printf("create socket failed ! error message :%s\n", strerror(errno));
return -1;
}
//设置组播IP地址
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
//设置结构sockaddr_in类型是TCP/IP
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.s_addr = inet_addr("224.10.10.2"); //设置为组播地址
char buf[1024] = {0};
while (1)
{
//发送数据到组播地址中
scanf("%s",buf);
sendto(st, buf, strlen(buf), 0, (struct sockaddr *)&addr,sizeof(addr));
memset(buf,0,sizeof(buf));
}
close(st);
return 0;
}
广播
int main(int arg, char * args[])
{
//创建UDP通信协议
int socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd < 0 )
{
perror("creat socket fail\n");
return -1;
}
//设置UDP的地址并绑定
struct sockaddr_in seraddr={0};
seraddr.sin_family = AF_INET; //使用IPv4协议
seraddr.sin_port = htons(atoi(argv[1])); //网络通信都使用大端格式
seraddr.sin_addr.s_addr = inet_addr("0.0.0.0"); //32位的整形 int ret = bind(socketfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret < 0)
{
perror("bind fail:");
return -1;
}
while(1)
{
char buf[1024]={0};
struct sockaddr_in seraddr1={0}; //保持发送者的IP地址信息
int len=sizeof(seraddr1);//直接使用结构体的大小对len进行初始
//数据的接收
int main(int argc ,char *argv[])
recvfrom(socketfd,buf,1024,0,(struct sockaddr*)&seraddr1,&len);
// char *inet_ntoa(struct in_addr in);
// uint16_t ntohs(uint16_t netshort);
printf("len=%d\n",len);
printf("IP=%d,port=%d\n",seraddr1.sin_addr.s_addr,seraddr1.sin_port);
printf("发送者的地址信息为:IP:%s,port=%d\n",inet_ntoa(seraddr1.sin_addr),ntohs(seraddr1.sin_port));
printf("buf = %s\n",buf);
}
}