9.5 网络编程
路由器:将两个不同的网络连接起来
交换机:将主机与主机连接起来
联网的目的:为了通讯
IP地址:给因特网上的每个主机分配的一个在全世界范围内唯一的标识符 (Linux命令:ifconfig)
分为IPV4和IPV6两种
IP地址组成:网络号+主机号 (共32位)
物理地址(MAC):48位 (也可以唯一标识主机) 不发生变化
端口号:用来在一台主机上唯一标识一个应用程序(进程) (16位) (有些特殊端口号不可使用)
网络协议:
一组网络规则的结合 是我们共同遵守的约定或标准
HTTP:超文本传输协议
FTP:文本传输协议
TELNET:是internet远程登录服务的标准协议
TCP:传输控制协议
UDP:用户数据协议
网络分层模型:
七层 OSI模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
四层 Tcp/ip模型 应用层 传输层 网络层 数据链路层
分层带来的好处:
各层之间是独立的 灵活性好 结构上可分割开 易于实现和维护 能促进标准化工作
数据链路层:相邻端口之间传输
网络层(IP)
传输层(端口):提供进程间通讯的能力
应用层:进程间通讯 两个主机之间 api接口
帧头 IP头部 Tcp/UDP头部 hello 帧尾
tcp协议 面向连接的 可靠的 流式服务
udp协议 无连接 不可靠的 数据报服务
主机字节序列和网络字节序列
主机字节序列分为大端和小端
套接字:通过网络进行数据的收和发
套接字地址: ip + port
套接字地址结构
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
}
sin_family:地址族
sin_port:端口号 需要用网络字节数表示
sin_addr:IPV4地址结构 s_addr以网络字节序列表示IPV4地址
IP地址转换函数:
IP地址表示:点分十进制字符串
!tcp服务器客户端编程流程:
服务端 ser 客户端 cli
socket socket
bind connect()
linsten() send()
accept recv()
recv() close()
send()
close()
(ser.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0); //tcp
if(sockfd == -1)
{
printf("create sockfd err\n");
return 0;
}
struct sockaddr_in saddr,caddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //IP地址不同
int res = bind(sockfd,(struct sockddr*)&saddr,sizeof(saddr));
if(res == -1)
{
printf("bind err\n");
return 0;
}
listen(sockfd,5);
while(1)
{
int len = sizeof(caddr);
int c = accept(sockfd,(struct sockaddr*)&caddr.&len); //可能阻塞
if(c<0)
{
continue;
}
char buff[128] = {0};
recv(c,buff,127,0); //阻塞
printf("buff=%s\n",buff);
send(c,"ok",2,0);
close(c);
}
}
(步骤:创建套接字 去连接 发数据 收数据)
(cli.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
return 0;
}
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = connect(sockfd,(struct sockddr*)&saddr,sizeof(saddr));
if(res == -1)
{
printf("连接服务器失败\n");
return 0;
}
char buff[128] = {0};
printf("input:\n");
fgets(buff,128,sdin);
send(sockfd,buff,strlen(buff),0);
memset(buff,0,sizeof(buff));
recv(socked,buff,127,0);
printf("buff=%s\n",buff);
close(sockfd);
}
先启动服务器 再运行客户端
查看服务器客户端信息命令:netstat -natp