文章目录
1. 网络
1.1 网络定义
网络是由若干结点和连接这些结点的链路组成,网络中的结点可以是计算机,交换机、路由器等设备。
-
网络设备有:交换机、路由器、集线器
-
传输介质有:双绞线、同轴电缆、光纤
网络示意图
1.2 互联网定义
多个网络的连接,目前最大的互联网就是我们常说的因特网。
互联网示意图
1.3 IP地址
IPV4地址:32位
IPV6地址:64位
IP地址组成:网络号+主机号
1.4 MAC地址
物理地址:MAC地址(唯一标识一台主机)(MAC寻址)
MAC地址示例:
端口号:在一台主机上唯一标识应用程序(进程)
特殊端口号:80号:web服务器使用,22号:远程登陆ssh
1.5 网络协议
网络协议就是一组网络规则的集合,是我们共同遵守的约定或标准。
◼ HTTP:超文本传输协议
◼ FTP: 文件传输协议
◼ TELNET : 是 internet 远程登陆服务的标准协议。
◼ TCP : 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可
靠的、基于字节流的传输层通信协议
◼ UDP :用户数据报协议
◼ IP : Internet Protocol 简称 IP,又译为网际协议或互联网协议
◼ ICMP :因特网控制报文协议
◼ ARP : 地址解析协议,是根据 IP 地址获取 MAC 地址的协议
◼ RARP : 逆地址解析协议
2. 网络分层
2.1 OSI模型 && TCP/IP模型
问题提出:为什么要分层?
- 分层以后各层之间是独立的
- 灵活性好
- 结构上可分割开
- 易于实现和维护
- 能促进标准化工作
IP地址存放在网络层
2.2 报头
IPV4头部结构如下:
TCP 协议报头:
将程序A的"hello"传给另外一台主机的应用程序B:
3. 网络编程
传输层
TCP协议:面向连接的,可靠的流式服务
UDP协议:无连接的,不可靠的数据报服务
3.1 主机字节序列和网络字节序列
-
主机字节序列分为大端字节序和小端字节序,不同的主机采用的字节序列可能不同。
-
将数据发送到网络时规定整形数据使用大端字节序,所以也把大端字节序成为网络字节序列
3.2 点分十进制
3.3 套接字地址结构
通过网络进行数据的传送,通用socket地址结构
#include<bits/socket.h>
struct sockaddr
{
fa_family_t sa_famliy;
char sa_data[14];
};
常见的协议族和对应的地址族如下:
3.4 代码示例
客户端——服务器端
TCP 服务器代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/socket.h>
6 #include<netinet/in.h>
7 #include<arpa/inet.h>
8
9 int main()
10 {
11 int sockfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字:IPV4,流式描述符,协议版本
12 if(sockfd==-1)
13 {
14 printf("socket err\n");
15 exit(1);//127.0.0.1测试
16 }
17 struct sockaddr_in saddr,caddr;//ipv4专用地址,saddr服务器端ip和端口,caddr客户端ip和端口,专用套接字地址
18 memset(&saddr,0,sizeof(saddr));
19 saddr.sin_family=AF_INET;//ipv4地址族
20 saddr.sin_port=(htons(6000));//知名端口:0-1024 专用端口:1024-4096 转为网络字节序列
21 saddr.sin_addr.s_addr=inet_addr("127.0.0.1");//结构体.无符号整型,将字符串转化为无符号整型,数据只能在本主机传递
22
23
24 int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//通用地址:套接字,套接字地址,套接字大小
25 if(res==-1)
26 {
27 printf("bind err\n");
28 exit(1);
29 }
30
31 res=listen(sockfd,5);//创建监听队列,监听队列大小,监听已经完成已经完成三次握手的监听队列的大小
32 if(res==-1)
33 {
34 printf("listen err\n");
35 exit(1);
36 }
37
38 while(1)
39 {
40 int len=sizeof(caddr);
41 //客户端
42 int c=accept(sockfd,(struct sockaddr*)&caddr,&len);//监听套接字(阻塞)
43 if(c<0)
44 {
45 continue;
46 }
47
48 char buff[128]={0};
49 int n=recv(c,buff,127,0);//接收数据
50 printf("recv(c=%d,n=%d)=%s\n",c,n,buff);
51
52 send(c,"ok",2,0);
53 close(c);
54 }
55 }
服务器的ip地址是固定下来的,客户端ip地址不需要固定
TCP客户端代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/socket.h>
6 #include<netinet/in.h>
7 #include<arpa/inet.h>
8
9 int main()
10 {
11 int sockfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字,客户端可以绑定,但是一般不绑定,
不指定客户端的ip和端口号,系统会临时分配端口号
12 if(sockfd==-1)
13 {
14 printf("sockfd err\n");
15 exit(1);
16 }
17 struct sockaddr_in saddr;//服务器地址
18 memset(&saddr,0,sizeof(saddr));
19 saddr.sin_family=AF_INET;
20 saddr.sin_port=htons(6000);
21 saddr.sin_addr.s_addr=inet_addr("127.0.0.1");//数据只能在本主机传递
22
23 int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//连接服务器未必可以成功
,三次握手从这里开始
24 if(res==-1)
25 {
26 printf("connect err\n");
27 exit(1);
28 }
29
30 char buff[128]={0};
31 printf("input \n");
32 fgets(buff,128,stdin);//数据返回给服务器
33
34 send(sockfd,buff,strlen(buff)-1,0);
35 memset(buff,0,128);
36 recv(sockfd,buff,127,0);//接收服务器返回的数据,recv返回值==0说明对端关闭
37
38 printf("buff=%s\n",buff);
39 close(sockfd);
40
41 }
运行结果
运行顺序
可以看到客户端和服务器端口的发送信息过程,先运行服务器,后运行客户端