1、网络是分层的
2.TCP/IP 协议引入
3、BS 和 CS
1.关于 TCP 理解的重点
2、TCP 如何保证可靠传输
1、TCP 的三次握手
客户端向服务器发送 SYN 报文,服务器回复 SYN + ACK 报文, 客户端回复 ACK 报文。三次握手的目的是为了防止已经失效的连接请求报文段突然又传送到了服务端,产生错误。
2、TCP 的四次挥手
3、基于 TCP 通信的服务模式
socket、bind、listen、accept 后处于监听状态。4、常见的使用来 TCP 协议的网络应用

1、建立连接
socket 函数:建立一个套接口,类似于 open,用来打开一个网络连接,如果成功则返 回一个网络文件描述符(int),之后我们操作这个网络连接都通过这个网络文件描述符。bind 函数:将 socket 建立的套接口与一个本地地址捆绑(主机地址/端口号)。listen 函数:把一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该 套接字的连接请求。accept 函数:开始接收从客户端发来的请求信息。connect 函数:发起对服务器的连接请求,三次握手在此时开始。2、发送和接收
send 和 write:都是用来发送信息。recv 和 read:都是用来接收信息。3、辅助性函数
inet_aton(将字符串转换成网络地址)、inet_addr(构建网络地址)、inet_ntoa(将网络地址转换成字符串)。inet_ntop(将网络地址转换成字符串)、inet_pton(将字符串转换成网络地址)。两者都兼容 IPv4 和 IPv6。4、表示 IP 地址相关数据结构
netinet/in.h。truct sockaddr:这个结构体是网络编程中用来表示一个 IP 地址的,注意这个 IP 地址 是 兼 容 IPv4 和 IPv6 的 , 在 实 际 编 程 中 这 个 结 构 体 会 被 struct sockaddr_in 或者 struct sockaddr_in6。struct sockaddr_in{
short int sin_family;//地址族。一般来说是AF_INET和PF_INET
unsigned short int sin_port;//端口号(使用网络字节顺序)。在linux下,端口号的范围是0~65535,0~1024范围的端口号已经被系统使用或者保留
struct in_addr sin_addr;//存储IP地址,使用in_addr这个数据结构。
unsigned char sin_zero[8];//未来将sockaddr_in结构与sockaddr结构对齐
};
typedef uint32_t in_addr_t;
struct in_addr{
in_addr_t s_addr;
};
1、inet_addr、inet_ntop、inet_pton:
#include
#include
#include
#include
#define IPADDR "192.168.1.103"
//0x66 01 a8 c0
//103 1 168 192
//网络字节序,其实就是大端模式,低字节在高地址
int main(void)
{
//使用inet_addr函数
in_addr_t addr=0;
addr=inet_addr(IPADDR);//构建网络地址
printf("addr=0x%x.\n",addr);//0x6601a8c0
return 0;
/*
//使用 inet_ntop 函数
struct in_addr addr={0};
char buf[50]={0};
addr.s_addr=0x6703a8c0;
inet_ntop(AF_INET,&addr,buf,sizeof(buf));//将网络地址转换成字符串
printf("ip addr = %s.\n", buf);
//使用 inet_pton 函数
int ret=0;
struct in_addr addr={0};
ret=inet_pton(AF_INET,IPADDR,&addr);//将字符串转换成网络地址
if(ret!=1) return -1;
printf("addr=0x%x.\n",addr.s_addr);
*/
}
1、服务器端程序编写
#include
#include
#include
#include
#include
#define SERPORT 9003
#define SERADDR "127.0.0.1"//本地地址
#define BACKLOG 100
int main(void)
{
int sockfd=-1,ret=-1,chilfd=-1;
socklen_t len=0;
struct sockaddr_in seraddr={0};
struct sockaddr_in cliaddr={0};
//第一步:先socket建立一个套接口,得到监听sockfd
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sockfd){
perror(socket);exit(-1);
}
printf("socketfd = %d.\n", sockfd);
//第二步:bind绑定sockfd和当前电脑的ip地址&端口号
seraddr.sin_family=AF_INET;//设置地址族为IPV4
seraddr.sin_port=htons(SERPORT);//设置地址的端口号信息
seraddr.sin_addr.s_addr=inet_addr(SERADDR);//设置IP地址
ret=bind(sockfd,(const struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret<0) return -1;
printf("bind success.\n");
//第三步:listen监听端口
ret=listen(sockfd,BACKLOG);//阻塞等待客户端来连接服务器
if(ret<0){
perror("listen");exit(-1);
}
printf("listen success.\n");
//第四步:accept阻塞等待客户端接入
clifd=accept(sockfd,(struct sockaddr*)&cliaddr,&len);
printf("连接已经建立,client fd=%d.\n",clifd);
return 0;
}
2、客户端程序的编写
#include
#include
#include
#include
#include
#define SERADDR "127.0.0.1"//服务器开放给我们的IP地址和端口号
#define SERPORT 9003
int main(void)
{
int sockfd=-1,ret=-1;
struct sockaddr_in seraddr={0};
//第一步:先socket建立一个套接口
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sockfd){
perror("socket");return -1;
}
printf("socketfd=%d.\n",sockfd);
//第二步:connect连接服务器
seraddr.sin_family=AF_INET;//IPV4
seraddr.sin_port=htons(SERPORT);//端口号
seraddr.sin_addr.s_addr=inet_addr(SERADDR);//设置IP地址
ret=connect(sockfd,(const struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret<0){
perror("listen");exit(-1);
}
printf("connect successfully.\n");
return 0;
}
1、客户端发送&服务器接收
//客户端反复发送
while(1){
pritnf("输入发送的内容\n");
scanf("s%",sendbuf);
ret=send(sockfd,sendbuf,strlen(sendbuf),0);
printf("发送了%d个字符\n",ret);
}
//服务器反复接收
while(1){
ret=recv(clifd,recvbuf,sizeof(recvbuf),0);
printf("client发送过来的内容是:%s.\n",recvbuf);
memset(recvbuf,0,sizeof(recvbuf));
}
2、服务器发送&客户端接收
//服务器给客户端发
strcpy(sendbuf,"hello world.");
ret=send(clifd,sendbuf,strlen(sendbuf),0);
printf("发送了%d个字符\n",ret);
//客户端接收
ret=recv(sockfd,recvbuf,sizeof(recvbuf),0);
printf("server发送过来的内容是:%s\n",recvbuf);
3、探讨:如何让客户端和服务器好好沟通
1、自定义应用层协议第一步:规定发送和接收方法。
//=======client.c文件
while(1){
//回合中第一步:客户端给服务器发送信息
printf("请输入要发送的内容");
scanf("%s",sendbuf);
ret=send(sockfd,sendbuf,strlen(sendbuf),0);
printf("向server发送了%d个字符.\n",ret);
//回合中第二步:客户端接收服务器的回复
memset(recvbuf,0,sizeof(recvbuf));
ret=recv(sockfd,recvbuf,sizeof(recvbuf),0);
printf("server发送过来的内容是:%s\n",recvbuf);
//回合中第三步:客户端解析服务器的回复,再做下一步定夺
}
//=======server.c文件
while(1){
//回合中第1步:服务器接收客户端消息
memset(recvbuf,0,sizeof(recvbuf));
ret=recv(clifd,recvbuf,sizeof(recvbuf),0);
printf("client发送过来的内容是:%s\n",recvbuf);
//回合中第二步:服务器回复客户端消息
printf("请输入要发送的内容\n");
scanf("%s",sendbuf);
ret=send(clifd,sendbuf,strlen(sendbuf),0);
printf("向 client 发送了%d 个字符\n", ret);
// 回合中第 3 步:服务器解析客户端的回复,再做下一步定夺
}
2、自定义应用层协议第二步:定义数据包格式
//=======client.c文件
#define CMD_REGISTER 1001 // 注册学生信息
#define CMD_CHECK 1002 // 检验学生信息
#define CMD_GETINFO 1003 // 获取学生信息
#define STAT_OK 30 // 回复 ok
#define STAT_ERR 31 // 回复出错了
typedef struct commu
{
char name[20];//学生姓名
int age;// 学生年龄
int cmd;// 命令码
int stat;//状态信息,用来回复
}info;
while(1){
//回合中第一步:客户端给服务器发送信息
info st1;
printf("请输入学生姓名\n");
scanf("%s",&st1.name);
printf("请输入学生年龄");
scanf("%d",&st1.age);
st1.cmd=CMD_REGISTER;
ret=send(sockfd,&st1,sizeof(st1),0);
printf("发送了 1 个学生信息\n");
//回合中第二步:客户端接收服务器信息
memset(&st1,0,sizeof(st1));
ret=recv(sockfd,&st1,sizeof(st1),0);
//回合中第三步:客户端解析服务器的回复,再做下一步定夺
if(st1.stat==STAT_OK)
printf("注册学生信息成功\n");
else
printf("注册学生信息失败\n");
}
//=======server.c文件
#define CMD_REGISTER 1001 // 注册学生信息
#define CMD_CHECK 1002 // 检验学生信息
#define CMD_GETINFO 1003 // 获取学生信息
#define STAT_OK 30 // 回复 ok
#define STAT_ERR 31 // 回复出错了
typedef struct commu
{
char name[20];//学生姓名
int age;// 学生年龄
int cmd;// 命令码
int stat;//状态信息,用来回复
}info;
while1(1){
info st;
//回合第一步:服务器接收客户端信息
memset(recvbuf,0,sizeof(recvbuf));
ret=recv(clifd,&st,sizeof(st),0)
printf("client发送过来的内容是:%s\n",recvbuf);
//回合第二步:服务器解析客户端数据包,然后干活
if(st.cmd==CMD_REGISTER){
printf("用户要注册学生信息.\n");
printf("学生姓名:%s,学生年龄:%d.\n",st.name,st.age);
/*此处服务器要进行真正的注册动作,一般是插入数据库一条信息
*************************************
*************************************/
//回合第三步:服务器发送客户端,回复
st.stat=STAT_OK;
ret = send(clifd, &st, sizeof(info), 0);
printf("注册完成\n");
}
if (st.cmd == CMD_CHECK) {}
if (st.cmd == CMD_GETINFO) {}
}
3、常用应用层协议:http、ftp……
1 、TCP、UDP的区别
2 、TCP、UDP的优缺点
3、TCP UDP适用场景
4、 TCP为什么是可靠连接?
5、OSI典型网络模型,简单说说有哪些
