网络
什么是网络:多个主机连在一起
什么是主机:交换机,基站,路由器,电脑,手机……(只要是能连接到网络的计算机都是主机)
如何连接·:无线电,光,电……
网络分层:
OIS参考模型 | 5层参考模型 |
---|---|
应用层 | |
表示层 | 应用层 |
会话层 | |
传输层 | 传输层 |
网络层 | 网络层 |
数据链路层 | 数据链路层 |
物理层 | 物理层 |
IP:区分网络中不同主机,本质是个整数,IPV4是个四字节整数
192.168.1.132 数点格式
网口:192.168.1.0 作为网关
子网掩码(255.255.255.0): 前面三段用来确定路由,最后一段用来确定主机,
子网掩码&ip==前面三个字节
子网掩码按位取反&ip==最后一个字节
端口:同一个主机上有多个端口,在网络通信的时候每一个进程占用唯一一个端口,浏览器占用80端口,使用时通常从小到大使用,个人所写应用程序一般使用5000以上的端口号,一共有65536个端口,建议使用一万左右,网络服务器一般是unix系统,大小端系统有区别,代码中使用端口号需要从小端转变成大端
#include<stdio.h>
union u{
char c[4];
int n;
}
int main(){
//类型决定存储方式和占用大小
//比如 int 4字节(有4个地址) 个人电脑一般为x86架构 , 网络的一般为arm架构 或者是其他架构
//x86 为小端系统 :高位数据在高地址上,低位数据在低地址上
//大段系统:高位数据在低地址上,低位数据在高地址上
//网络服务器都是大端系统
union uu;
uu.n=0x11223344;
printf("%x %x %x %x \n",uu.c[0],uu.c[1],uu.c[2],uu.c[3]);
return 0;
}
打印结果为 :44 33 22 11
TCP协议
TCP协议:
编程模型 | |
---|---|
服务器 | 客户端 |
1.创建socket 函数 | 1.创建socket |
2.确定服务器协议地址簇 struct sockaddr_in 结构 | 2.获取服务器协议地址簇 struct sockaddr_in 结构 |
3.绑定 bind函数 | |
4.监听listen函数 | |
5.接收连接accept函数来接受客户端的信息; accept函数是个阻塞函数 | 3.连接服务器connect函数 |
6.通信 接收信息 revc函数 | 4.通信 send函数 |
7.断开连接 close | 5.断开连接 close |
服务器函数
socket
函数:
通信媒介:
TCP使用:SOCK_STREAM;
UPD使用:SOCK_DGRAM;
bind
绑定函数:
第一个参数为:socket
函数返回值
第二个参数为:协议地址簇地址
第三个参数为:协议地址簇长度
struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx /
char sa_data[14]; / 14字节的协议地址*/
};
以上为通用socket地址簇
Internet socket地址簇:用下面的结构,二者可以进行类型转换
struct sockaddr_in {
short int sin_family; /* 地址族 /
unsigned short int sin_port; / 端口号 /
struct in_addr sin_addr; / Internet地址 /
unsigned char sin_zero[8]; / 与struct sockaddr一样的长度 ,可以不使用*/
};
htons
函数
htons
是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
atoi
函数:把字符串转换成整型数.
inet_addr
函数:inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值
inet_aton()
:函数是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP地址。
inet_ntoa
:返回点分十进制的字符串在静态内存中的指针。
示例:
listen
函数:
第一个参数:socket返回值
第二个参数:侦听队列的长度
accept
函数:
recv
函数:
示例
服务器:
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
int sockFd,ClientSocket;//服务器 客户端
void hand(){
//7.断开连接
close(sockFd);
close(ClientSocket);
printf("bye\n");
exit(0);
}
int main(int argc,char* argv[]){
if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
printf("IP:%s port:%d\n",argv[1],atoi(argv[2]));
//7.断开连接
signal(2,hand);//SIGINT 终端中断 2
//1.创建socket
sockFd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sockFd)printf("创建Socket失败:%m\n"),exit(-1);
printf("创建socket成功\n");
/*
atoi函数:把字符串转换成整型数.
inet_addr函数:inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值
inet_aton():函数是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP址。
inet_ntoa:返回点分十进制的字符串在静态内存中的指针。
htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
*/
//2.创建服务器协议地址簇
struct sockaddr_in addr={0};//in为linux ,un为unix
addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址
addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
//3.绑定
int r=bind(sockFd,(struct sockaddr *)&addr,sizeof(addr));
if(r==-1)printf("绑定失败:%m\n"),close(sockFd),exit(-2);
printf("绑定成功\n");
//4.监听
int l=listen(sockFd,10);
if(l==-1)printf("监听失败:%m\n"),close(sockFd),exit(-2);
printf("监听成功\n");
//5.接收客户端连接
struct sockaddr_in ClientAddr={0};//客户端协议地址簇
int len=sizeof(ClientAddr);
ClientSocket=accept(sockFd,(struct sockaddr *)&ClientAddr,&len);
if(-1==ClientSocket)printf("服务器崩溃:%m\n"),close(sockFd),exit(-2);
printf("有客户端连接服务器:%s\n",inet_ntoa(ClientAddr.sin_addr));//将IP地址转换为它所对应的点分十进制串
//inet_ntoa:返回点分十进制的字符串在静态内存中的指针。
//6.通信
char buff[256];
while(1)
{
int r=revc(ClientSocket,buff,255,0);
if(r>0){
buff[r]=0;//添加结束字符
printf(">>%s\n",buff);
}
}
//7.断开连接
//signal(2,hand);
return 0;
}
客户端函数:
connect
函数与bind
函数对应:
send
函数与recv
函数对应:
客户端:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<string.h>
int ClientSocket;//客户端
void hand(){
//5.断开连接
close(ClientSocket);
printf("bye\n");
exit(0);
}
int main(int argc,char* argv[]){
if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
printf("IP:%s port:%d\n",argv[1],atoi(argv[2]));
//5.断开连接
signal(2,hand);
//1.创建socket
ClientSocket=socket(AF_INET,SOCK_STREAM,0);
if(-1==ClientSocket)printf("创建Socket失败:%m\n"),exit(-1);
printf("创建socket成功\n");
/*
atoi函数:把字符串转换成整型数.
inet_addr函数:inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值
inet_aton():函数是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP址。
inet_ntoa:返回点分十进制的字符串在静态内存中的指针。
htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
*/
//2.获取服务器协议地址簇
struct sockaddr_in addr={0};//in为linux ,un为unix
addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址
addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
//3.连接服务器
int r=connect(ClientSocket,(struct sockaddr *)&addr,sizeof(addr));
if(r==-1)printf("连接服务器失败:%m\n"),close(ClientSocket),exit(-2);
printf("连接服务器成功\n");
//4.通信
char buff[256];
while(1)
{
printf("请输入\n");
scanf("%s",buff);
send(ClientSocket,buff,strlen(buff),0);
}
return 0;
}
ifconfig
命令查看ip端口号
文件传输
文件传输(在已经建立好连接的情况下去完成):
接收端:服务器 | 发送端:客户端 |
---|---|
1. 等待客户端发送 | 1.发送文件名 |
2.接收文件名并创建文件 | 2.获取并发送文件大小 |
3.接收文件大小新建文件 | 3.发送文件名和文件大小 |
4.循环接收并写入数据 | 4. 循环读取并发送 |
5.接收数据足够,关闭文件 | 5. 发送完毕,关闭 |
示例
接收端:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<fcntl.h>
int serverSocket,clientSocket;//服务器 客户端
int main(){
//1.创建socket
serverSocket=socket(AF_INET,SOCK_STREAM,0);
if(-1==serverSocket)printf("创建Socket失败:%m\n"),exit(-1);
printf("创建socket成功\n");
//2.创建服务器协议地址簇
struct sockaddr_in addr={0};//in为linux ,un为unix
addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
addr.sin_addr.s_addr=inet_addr("127.0.0.1");//sin_addr.s_addr获取Internet地址
addr.sin_port=htons(atoi(10086));//整形小段转成大端
//3.绑定
int r=bind(serverSocket,(struct sockaddr *)&addr,sizeof(addr));
if(r==-1)printf("绑定失败:%m\n"),close(serverSocket),exit(-2);
printf("绑定成功\n");
//4.监听
int l=listen(serverSocket,10);
if(l==-1)printf("监听失败:%m\n"),close(serverSocket),exit(-2);
printf("监听成功\n");
//5.接收客户端连接
struct sockaddr_in ClientAddr={0};//客户端协议地址簇
int len=sizeof(ClientAddr);
v=accept(serveSocket,(struct sockaddr *)&ClientAddr,&len);
if(-1==clientSocket)printf("服务器崩溃:%m\n"),close(serverSocket),exit(-2);
printf("有客户端连接服务器:%s\n",inet_ntoa(ClientAddr.sin_addr));//将IP地址转换为它所对应的点分十进制串
//6.通信
//文件操作
//2.接收文件名
char buff[256];
char fileName[256]={0};
int fileSize;
int count=0;
r=recv(clientSocket,fileName,255,0);
if(r>0)
{
printf("接收文件名:%s\n",fileName);
}
//3.接收文件大小
r=recv(clientSocket,(char*)&fileSize,4,0);
if(r==4)
{
printf("接收到文件大小:%d\n",fileSize);
}
//4.循环接收并写入文件
int fd=fopen(fileName,O_CREAT|O_WRONLY,0666);
while(1){
r=recv(clientSocket,buff,1024,0);
if(r>))
{
write(fd,buff,r);
count+=r;
if(count>=fileSize)break;
}
}
//5.关闭文件
close(fd);
sleep(1);
printf("接收完毕");
close(clientSocket);
close(serverSocket);
return 0;
}
发送端:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
int clientSocket;//客户端
int main(int argc,char* argv[]){
//1.创建socket
clientSocket=socket(AF_INET,SOCK_STREAM,0);
if(-1==clientSocket)printf("创建Socket失败:%m\n"),exit(-1);
printf("创建socket成功\n");
//2.获取服务器协议地址簇
struct sockaddr_in addr={0};//in为linux ,un为unix
addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
addr.sin_addr.s_addr=inet_addr("127.0.0.1");//sin_addr.s_addr获取Internet地址
addr.sin_port=htons(atoi(10086));//整形小段转成大端
//3.连接服务器
int r=connect(clientSocket,(struct sockaddr *)&addr,sizeof(addr));
if(r==-1)printf("连接服务器失败:%m\n"),close(clientSocket),exit(-2);
printf("连接服务器成功\n");
//4.通信
//发送文件操作
//1.发送文件名
int fd=open(argv[1],O_WRONLY);
if(fd==-1)printf("打开文件失败:%m\n"),close(clientSocket),exit(-1);
printf("打开文件成功\n");
//2.获取文件大小
int fileSize=0;
strcut stat st={0};
stat(argv[1],&st);
printf("文件的大小为:%d\n",st.st_size);
//3.发送文件名和文件大小
send(clientSocket,argv[1],strlen(argv[1]),0);//发送文件名
send(clientSocket,(char*)&st.st_size,4,0);//发送文件大小
//4. 循环读取并发送
char buff[1024];
while(1)
{
r=read(fd,buff,1024);
if(r>0){
send(clientSocket,buff,0);
}else{
break;
}
}
//5. 发送完毕,关闭
printf("发送完毕");
close(fd);
sleep(1);
close(clientSocket);
return 0;
}
UDP协议:
编程模型 | |
---|---|
服务器 | 客户端 |
1.创建socket | 1.创建socket |
2.确定服务器地址簇 | 2.获取服务器协议地址簇 |
3.绑定 | |
4.通信 | 3.通信 |
5.断开连接 | 5.断开连接 |
函数:
recvfrom
函数:
sendto
函数:
示例
服务器:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
int serverSocket;//服务器
void hand(){
//5.断开连接
close(serverSocket);
printf("bye\n");
exit(0)
}
int main(int argc,char* argv[]){
if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
printf("IP:%s port:%d\n",argv[1],atoi(argv[2]));
//7.断开连接
signal(2,hand);
//1.创建socket
serverSocket=socket(AF_INET,SOCK_DGRAM,0);
if(-1==serverSocket)printf("创建Socket失败:%m\n"),exit(-1);
printf("创建socket成功\n");
//2.创建服务器协议地址簇
struct sockaddr_in addr={0};//in为linux ,un为unix
addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址
addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
//3.绑定
int r=bind(serveSocket,(struct sockaddr *)&addr,sizeof(addr));
if(r==-1)printf("绑定失败:%m\n"),close(serverSocket),exit(-2);
printf("绑定成功\n");
//4.通信
char buff[256];
struct sockaddr_in clientAddr={0};
int len=sizeof(clientAddr);
while(1)
{
int r=recvfrom(serverSocket,buff,255,0,(struct sockaddr *)&clientAddr,&len);//接收客户端的协议地址簇,像协议地址簇发东西
if(r>0){
buff[r]=0;//添加结束字符
printf(">>%s\n",buff);
sendto(serverSocket,"服务器",
strlen("服务器"),0,(struct sockaddr *)&clientAddr,sizeof(clientAddr));//发送
}
}
return 0;
}
客户端:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
int clientSocket;// 客户端
void hand(){
//4.断开连接
close(clientSocket);
printf("bye\n");
exit(0);
}
int main(int argc,char* argv[]){
if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
printf("IP:%s port:%d\n",argv[1],atoi(argv[2]));
//4.断开连接
signal(2,hand);
//1.创建socket
clientSocket=socket(AF_INET,SOCK_DGRAM,0);
if(-1==clientSocket)printf("创建Socket失败:%m\n"),exit(-1);
printf("创建socket成功\n");
//2.创建服务器协议地址簇
struct sockaddr_in addr={0};//in为linux ,un为unix
addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址
addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
//3.通信
char buff[256];
char temp[256];
int len=sizeof(addr);
int r;
while(1)
{
printf("请发送\n");
scanf("%s",buff);
sendto(clientSocket,buff,strlen(buff),0,(struct sockaddr *)&addr,sizeof(addr));
r=recvfrom(clientSocket,temp,255,0,(struct sockaddr *)&addr,&len);
if(r>)){
temp[r]=0;
printf("服务器发来信息%s\n",temp);
}
}
return 0;
}