该章的pdf版本
1.网络应用程序设计模式:
2.协议的概念
○ 规则: 数据传输和数据解释的规则
○ 原始协议 ------>(改进、完善)------> 标准协议
○ 典型协议:TCP/UDP HTTP FTP IP ARP
7层模型 - OSI(开放式系统互联通信参考模型(英语:Open System Interconnection Reference Model)):
物 (物理层)-- 双绞线, 光纤
数 (数据链路) – 数据的传输和错误检测
网 (网络层)-- 为数据包选择路由
传 (传输层)-- 提供端对端的接口 tcp/udp
会 (会话层) – 解除或建立与别的节点的联系
表 (表示层)-- 数据格式化,代码转换,数据加密
应 (应用层)-- 文件传输,电子邮件,文件服务,虚拟终端
4层模型 - TCP/IP: 网络接口层 网络层 传输层 应用层
除应用层程序员自己做外,其他层都是操作系统(Windows,Linuc操作系统)做。
注意:以下协议是各层比较常见的协议,并不是只有以下的协议。
— 借助mac地址完成数据报传递
□arp数据报 --根据IP获取mac地址
实例:
IP段格式:
4位版本: ipv4 ipv6
8位生存时间(TTL): 最多能经过多少跳
32位源IP地址: 数据发送端地址
32位目的IP地址: 数据接收端地址
DP数据包格式:
16位源端口:
16位目的端口:
进程
-进程ID
-网络环境中
-端口:16位
○2的16次方
○65535
TCP数据报格式
16位源端口
16位目的端口32位序号
32位确认序号6个标志位
16位滑动窗口
存储空间
○tcp: 面向连接的安全的流式传输协议
○什么是socket
○浏览器-http
管道:
内核缓冲区。
内存中一块存储空间。
管道的读写两端分别对应一个文件描述符。
套接字:
○创建成功, 得到一个文件描述符fd
○fd操作的是一块内核缓冲区
默认也是阻塞的(阻塞不阻塞看的是fd类型)。
网络字节序
○大端:-网络字节序
数据的高位字节-存储在内存的低地址位
○小端:-主机字节序
数据的高位字节-存储在内存的高地址位
常见主机数据是小端存储
大小端转换函数
头文件: #include
类型:int -> int
主机字节顺序 --> 网络字节顺序
uint16_t htons(uint16_t hostshort); 端口
uint32_t htonl(uint32_t hostlong);IP
网络字节顺序 --> 主机字节顺序
uint16_t ntohs(uint16_t netshort);端口
uint32_t ntohl(uint32_t netlong);IP
a.指定IP-字符串(点分十进制)
○本地IP转网络字节序 字符串–>int(大端方式存储)
int inet_pton(int af, const char *src, void *dst);
参数:
□af
□src
□dest
○网络字节序转本地IP int-> 字符串
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
参数:
□af
af_inet
□src
网络字节序的整形IP
□dst
□size
○sockaddr
○sockaddrin
○sockaddrun
struct sockaddr{
/* address family, AF_xxx */
sa_family_t sa_family;
/* 14 bytes of protocol address */
char sa_data[14];
};
struct sockaddr_in {
__kernel_sa_family_t sin_family;// 地址族协议
__be16 sin_port;// 端口
struct in_addr sin_addr;//IP地址
unsigned char __pad[__SOCK_SIZE__ -sizeof(short int) -
sizeof(unsigned short int) -sizeof(struct in_addr)];
};
struct in_addr {
__be32 s_addr;
};
○int socket(int domain, int type, int protocol);
○int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
○int listen(int sockfd, int backlog);
○int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
○int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
○服务器端:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, const char* argv[])
{
// 创建监听的套接字
int lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd == -1)
{
perror("socket error");
exit(1);
}
// lfd 和本地的IP port绑定
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET; // 地址族协议 - ipv4
server.sin_port = htons(8888);
server.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(lfd, (struct sockaddr*)&server, sizeof(server));
if(ret == -1)
{
perror("bind error");
exit(1);
}
// 设置监听
ret = listen(lfd, 20);
if(ret == -1)
{
perror("listen error");
exit(1);
}
// 等待并接收连接请求
struct sockaddr_in client;
socklen_t len = sizeof(client);
int cfd = accept(lfd, (struct sockaddr*)&client, &len);
if(cfd == -1)
{
perror("accept error");
exit(1);
}
printf(" accept successful !!!\n");
char ipbuf[64] = {0};
printf("client IP: %s, port: %d\n",
inet_ntop(AF_INET, &client.sin_addr.s_addr, ipbuf, sizeof(ipbuf)),
ntohs(client.sin_port));
// 一直通信
while(1)
{
// 先接收数据
char buf[1024] = {0};
int len = read(cfd, buf, sizeof(buf));
if(len == -1)
{
perror("read error");
exit(1);
}
else if(len == 0)
{
printf(" 客户端已经断开了连接 \n");
close(cfd);
break;
}
else
{
printf("recv buf: %s\n", buf);
// 转换 - 小写 - 大写
for(int i=0; i