① 什么是IP地址
IP地址:是计算机在网络中唯一的标识,由两部分组成
分别是表示网络区域的网络号,和该网络下的主机编号
网络号:确定计算机所从属于哪个局域网络
主机号:计算机在该局域网络下的一个编号
② IP的划分,有几类IP地址
五类IP地址
A类IP地址 1.0.0.0——————255.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 组播IP
E类网络 240.0.0.0————255.255.255.255 保留或实验室使用
③ IP地址中200.0.0.0这个IP属于哪一类网络?
C类网络,C类网络从192.0.0.0——————223.255.255.255
④ 什么是端口号,端口号的作用?
主机号是为了区分同一主机上的多个进程
使用端口号来进行处理。端口号是一个无符号的2字节的整数
取值范围为[0 -65535] 2^16-1
其中[0 ——1023] 号端口号编程是不适用,已经被占用
可以使用的是[1024 --49151]
[49152 --65535]号端口号是临时端口号,这部分是客户端运行时动态选择的
⑤ 对字节序的理解
字节序引入主要是因为不同计算机架构选择了不同的存储方式
主机字节序,存储多字节整数,主机字节序分为大端存储和小端存储
网络字节序,存储多字节整数,是大端存储
通过函数可以实现主机字节序和网络字节序之间的相互转换。
主机字节序决定了数据在主机内存中的排列方式,
对于主机内部的数据处理至关重要;而网络字节序
则确保了不同系统之间的通信能够正常进行,
通过统一的字节序规则,实现了数据的正确传输和解析
⑥ 7层网络体系结构
应用层 会话层 表示层 传输层
网络层 数据链路层 物理层
⑦ TCP和UDP 通信的区别
相同:同属于传输层的协议TCP:----->稳定 传输控制协议
TCP的优点
1》提供面向连接的,可靠的数据传输协议
2>> 传输过程中,数据无误,数据无丢失,无失去顺序,数据无重复
3>> 每个数据都需要数据应答包,若没有应答,会一直重复上面的包发送直到正确为止
缺点:
4>>数据传输效率地低,耗费资源多
5>>缺点:数据的收发不是同步的,
(1)为了提高效率, TCP会将多个较小,并且发送间隔短的数据包粘成一个数据包发送。
(2)粘包算法称之为 Nagle算法
6>>TCP的使用场景 对传输质量要求高,以及传输达礼郎数据的通信,在需要可靠通信的场合 (如账号登录,大型文件下载)
UDP ----->快速 用户数据报协议
优点:1 传输速度快,实时性高
2 收发是同步的,不需要粘包
缺点: 3 面向无连接的,不保证数据可靠性,尽最大能力传输,
4传输过程中不保证数据的丢失,重复,失序等现象
5限制每次传输数据的大小,超出部分直接忽略删除
6》》适用场景:广播,通讯软件等
⑧ TCP通信过程中,服务器端实现的流程
<1>socket 函数创建一个用于连接的套接字文件描述符
<2>bind 函数绑定IP和端口号
<3>listen函数将套接字设置为被动监听模式,准备接收客户请求
TCP服务端
int main(int argc, const char *argv[])
{
//1 为通信创建一个端点
int sfd=socket(AF_INET,SOCK_STREAM,0);
//参数1 说明使用的是IPv4网络
//参数2 说明使用的是TCP面向连接的通讯方式
//参数3,由于参数2已经指定通信方式,直接为0
if(sfd ==-1)
{
perror("socket error");
return -1;
}
printf("socket success sfd=%d\n",sfd); // 3 (0 stdin ,stdout 1,stderr 2)
// 2 绑定IP地址和端口号
// 2.1 准备地址信息结构体
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr =inet_addr(SER_IP);//嵌入一个小的结构体
//绑定工作
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)))
{
perror("bind error");
return -1;
}
printf("bind success\n");
// 3 将套接字设置成被动监听状态;
//
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
printf("listen success\n");
// 4 阻塞等待客户端的连接
// 4.1 定义用于接受客户端信息的容器
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
int newfd =accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd ==-1)
{
perror("accept error");
return -1;
}
printf("accept success\n");
printf("[%s %d]发送来连接请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
// 5 与客户端进行相互通信
char rbuf[128]={}; //用于读取消息内容的容器
while(1)
{
// 清空容器
bzero(rbuf,sizeof(rbuf));
//从套接字读取数据
int res =read(newfd,rbuf,sizeof(rbuf));
if(res == 0)
{
printf("客户端已经下线\n");
break ;
}
//将读取到的消息展示出来
printf("[%s %d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf );
//将收到的消息处理一下,回复给客户端
strcat(rbuf,"OK");
//将消息发送给客户端
write(newfd,rbuf,strlen(rbuf));
printf("发送成功\n");
}
// 6 关闭套接字
close(sfd);
return 0;
}
TCP客户端
// TCP 通信客户端实现 server-side 服务端 client-side 客户端 端口号 port number
int main(int argc, const char *argv[])
{
//1 创建用于通信的套接字文件描述符
int cfd=socket(AF_INET,SOCK_STREAM,0);
if(cfd == -1)
{
perror("socket error");
return -1;
}
printf("socket success cfd =%d\n",cfd);
//2 绑定IP地址和端口 对于客户端可以不必要绑定IP地址和端口
//2.1 填充客户端地址信息结构体
struct sockaddr_in cin;
cin.sin_family =AF_INET;
cin.sin_port =htons(CLI_PORT);
cin.sin_addr.s_addr =(inet_addr(CLI_IP));
//2.2 绑定
if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))== -1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
// 3.1 准备对端(对面)地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr =inet_addr(SER_IP);
//3.2连接服务器
if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("connect error");
return -1;
}
printf("connect success\n");
//4 数据收发
//
char wbuf[128]="";
char rbuf[128]="";
while(1)
{
//从终端上获取要发送的数据
fgets(wbuf,sizeof(wbuf),stdin);
wbuf[strlen(wbuf)-1]=0;
printf("发送成功\n");
//接收服务器发来的消息
//
bzero(rbuf,sizeof(rbuf));
printf("服务器发来的消息为:%s\n",rbuf);
}
//关闭套接字
close(cfd);
return 0;
}
UDP服务端
#include <myheader.h>
#define SER_PORT 8888
#define SER_IP "192.168.230.128"
int main(int argc, const char *argv[])
{
/* ****server-side **** */
//创建用于通信的套接字文件描述符 sfd -->service file descriptor 服务文件描述符
int sfd =socket(AF_INET,SOCK_DGRAM,0);
if(sfd == -1)
{
perror("socket error");
return -1;
}
printf("sfd=%d\n",sfd);
//绑定IP地址和端口号
// 2.1 填充地址信息结构体
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr =inet_addr(SER_IP);
// 2.2 绑定
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin) )== -1)
{
perror("bind erroe");
return -1;
}
// 3 数据收发
char rbuf[128]="";
//准备接收对端的地址信息
struct sockaddr_in cin;
socklen_t addrlen =sizeof(cin);
while(1)
{
//清空容器
bzero (rbuf,sizeof(rbuf));
//读取数据
//
recvfrom(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&cin,&addrlen);
printf("收到的消息为:%s\n",rbuf);
//将收到的消息加上一个OKK回复过去
strcat(rbuf,"OKK");
if(sendto (sfd,rbuf,strlen(rbuf),0,(struct sockaddr*)&cin,sizeof(cin) == -1))
{
perror("sendto error");
return -1;
}
printf("发送成功\n");
}
close(sfd);
return 0;
}
UDP客户端
int main(int argc, const char *argv[])
{
// ① 创建用于通信的套接字文件描述符
int cfd =socket(AF_INET,SOCK_DGRAM,0);
if(cfd == -1)
{
perror("socket error");
return -1;
}
// ② 绑定IP地址和端口号
// 2.1 填充地址信息结构体
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr =inet_addr(SER_IP);
//2.2 绑定
if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//③ 数据收发
char wbuf[128] ="";
//填充服务器的地址信息结构体
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr =inet_addr(SER_IP);
char rbuf[128] ="";
while(1)
{
//清空容器
bzero(wbuf,sizeof(wbuf));
bzero(rbuf,sizeof(rbuf));
//从终端获取信息
fgets(wbuf,sizeof(wbuf),stdin);
wbuf[strlen(wbuf)-1]=0;
//将消息发送给服务器
sendto(cfd,rbuf,sizeof(rbuf),0,NULL,NULL);
printf("接收到的服务器消息为:%s\n",rbuf);
//④ 关闭套接字
close(cfd);
}
return 0;
}