linux网络编程大杂烩==Linux应用编程7
一、Linux 网络编程框架
1、网络是分层的
- (1)OSI 七层模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。
- (2)网络为什么要分层:互联网及其复杂,需要分层以便更好地实现网络通信。
2.TCP/IP 协议引入
- (1)TCP/IP 协议是用得最多的网络实现协议。
- (2)TCP/IP 协议分为四层,对应着 OSI 的七层:应用层(包括 OSI 的表示层和会话层)、传输层、网络层、链路层(包括 OSI 的物理层)。
- (3)网络编程时最关注应用层,了解传输层,网络层和链路层不用管。
3、BS 和 CS
- (1)BS 架构:broswer-server,浏览器-服务器框架。
- (2)CS 架构:client-server,客户端-服务器框架
二、TCP 协议的学习 1
1.关于 TCP 理解的重点
- (1)TCP 协议工作在传输层,对上服务 socket 接口,对下调用 IP 层
- (2)TCP 协议面向连接,通信前必须三次握手建立连接关系。
- (3)TCP 协议提供可靠传输,不怕丢包、乱序等问题。
2、TCP 如何保证可靠传输
- (1)TCP 在传输有效信息前要求通信双方必须先握手建立连接。
- (2)TCP 接收方收到数据包后会发 ack 给发送方,若发送方未收到 ack 则丢包重传。
- (3)TCP 有效内容会附带校验信息,以防止内容在传输过程中出现错误。
- (4)发送方会给各个报文编号,接收方收到报文后会校验编号,一旦顺序错误则重传。
- (5)TCP 会根据网络情况来调节发送速率(滑动窗口协议)
三、TCP 协议的学习 2
1、TCP 的三次握手
- (1)建立连接需要三次握手:
客户端向服务器发送 SYN 报文,服务器回复 SYN + ACK 报文, 客户端回复 ACK 报文
。三次握手的目的是为了防止已经失效的连接请求报文段突然又传送到了服务端,产生错误。- ①第一次握手:客户端发送一个 TCP 标志位 SYN=1,ACK=0 的数据包给服务端,并随机会产 生一个 Seq=J。当服务端接收到这个数据后,服务端由 SYN=1 可知客户端是 想要建立连接。
- ②第二次握手:服务端要对客户端的联机请求进行确认,向客户端发送应答号 ACK=1、SYN=1 , 确认号 Ack=J+1,此值是客户端的序列号加 1,还会产生一个随机的序列号 Seq=K,这样就告诉客户端可以进行连接。
- ③第三次握手:客户端收到数据后检查 Ack 是否为 J+1,以及标志位 ACK 的值是否为 1,若 为 1,则会发送 ACK=1、确认号码 Ack=K+1,告诉服务端,你的请求连接被确 认,连接可以建立,Client 和 Server 进入 ESTABLISHED 状态,完成三次握手, 随后 Client 与 Server 之间可以开始传输数据了。
- (2)建立连接的条件:服务器 accept 时客户端主动发起 connect。
2、TCP 的四次挥手
- (1)关闭连接需要四次挥手:客户端向服务器发送FIN报文,服务器回复ACK报文;服务器向客户端发送FIN+ACK报文,客户端回复ACK报文。(客户端与服务器可互换)
- (2)客户端和服务器都可以主动发起关闭。
- 注:这些握手协议已经封装在 TCP 协议内部,socket 编程接口平时不用管
3、基于 TCP 通信的服务模式
- (1)具有公网 IP 地址的服务器(或者使用动态 IP 地址映射技术)。
- (2)服务器端
socket、bind、listen、accept
后处于监听状态。 - (3)客户端 socket 后,直接 connect 去发起连接。
- (4)服务器收到申请并同意客户端接入后会建立 TCP 连接,然后双方开始收发数据。
- (5)双方均可发起关闭连接。
4、常见的使用来 TCP 协议的网络应用
- (1)http、ftp
- (2)QQ 服务器
- (3)mail 服务器
四、socket 编程接口介绍
1、建立连接
- (1)
socket
函数:建立一个套接口,类似于open
,用来打开一个网络连接,如果成功则返 回一个网络文件描述符(int),之后我们操作这个网络连接都通过这个网络文件描述符。 - (2)
bind
函数:将 socket 建立的套接口与一个本地地址捆绑(主机地址/端口号)。 - (3)
listen
函数:把一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该 套接字的连接请求。 - (4)
accept
函数:开始接收从客户端发来的请求信息。 - (5)
connect
函数:发起对服务器的连接请求,三次握手在此时开始。
2、发送和接收
- (1)
send 和 write
:都是用来发送信息。 - (2)
recv 和 read
:都是用来接收信息。
3、辅助性函数
- (1)
inet_aton
(将字符串转换成网络地址)、inet_addr
(构建网络地址)、inet_ntoa
(将网络地址转换成字符串)。 - (2)
inet_ntop
(将网络地址转换成字符串)、inet_pton
(将字符串转换成网络地址)。两者都兼容 IPv4 和 IPv6。
4、表示 IP 地址相关数据结构
- (1)都定义在
netinet/in.h
。 - (2)
truct sockaddr
:这个结构体是网络编程中用来表示一个 IP 地址的,注意这个 IP 地址 是 兼 容 IPv4 和 IPv6 的 , 在 实 际 编 程 中 这 个 结 构 体 会 被 struct sockaddr_in 或者 struct sockaddr_in6。 - (3)typedef uint32_t in_addr_t:网络内部用来表示 IP 地址的类型。
struct sockaddr_in{short int sin_family;//地址族。一般来说是AF_INET和PF_INETunsigned 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;
};
五、IP 地址转换函数实践
1、inet_addr、inet_ntop、inet_pton:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#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);//0x6601a8c0return 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);
*/
}
六、socket 编程实践 1
1、服务器端程序编写
- (1)socket。 (sockfd)创立套接字伪文件
- (2)bind。 往套接字上面绑定port和ip(本身)
- (3)listen。允许同时有多少客户端跟我建立连接
- (4)accept:返回值是一个 fd(chilfd),accept 正确返回表示已经与客户端建立 TCP 连接,之后需 要通过这个连接对应的 fd 来和客户端进行读写操作。
- 注意:socket 返回的 fd 叫监听 fd,是用来监听客户端的,不能读写;accept 返回的 fd 叫连 接 fd,用来读写。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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建立一个套接口,得到监听sockfdsockfd=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;//设置地址族为IPV4seraddr.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、客户端程序的编写
- (1)socket。
- (2)connect。connect和bind参数一致,前者是对方的地址后者是自己的地址
- 概念:端口号,实质就是一个数字编号,用来在一台主机的操作系统中唯一地标识一个能上网的进程。网络上传输的每一个数据包都包含了发送方和接收方的 IP 地址和端口号。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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;//IPV4seraddr.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;
}
七、socket 编程实践 2
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)客户端和服务器原则上都可以任意收和发,但实际上双方必须配合
- (2)必须了解到的一点:client 和 server 之间的通信是异步的,这就是问题的根源。
- (3)解决方案:依靠应用层协议来解决,就是 server 和 client 事先做好一系列通信约定。
八、socket 编程实践 3==important
1、自定义应用层协议第一步:规定发送和接收方法。
- (1)规定连接建立后由客户端主动向服务器发送一个请求数据包,服务器收到后回复一个 应答数据包,这就是一个通信回合。
- (2)整个连接的通信就是由 N 多个回合组成的。
//=======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");elseprintf("注册学生信息失败\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……
九、TCP与UDP
1 、TCP、UDP的区别
- TCP—传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。
- UDP—用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
- 区别:
- 1)TCP是面向连接的,UDP是面向无连接的
- 2)UDP程序结构较简单
- 3)TCP是面向字节流的,UDP是基于数据包的
- 4)TCP保证数据正确性,UDP可能丢包
- 5)TCP保证数据顺序到达,UDP不保证
2 、TCP、UDP的优缺点
- TCP优点:可靠稳定。TCP的可靠体现在TCP在传输数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完之后,还会断开来连接用来节约系统资源。TCP缺点:慢,效率低,占用系统资源高,易被攻击在传递数据之前要先建立连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞机制等都会消耗大量时间,而且要在每台设备上维护所有的传输连接。然而,每个连接都会占用系统的CPU,内存等硬件资源。因为TCP有确认机制、三次握手机制,这些也导致TCP容易被利用,实现DOS、DDOS、CC等攻击。
- UDP优点:快,比TCP稍安全UDP没有TCP拥有的各种机制,是一种无状态的传输协议,所以传输数据非常快,没有TCP的这些机制,被攻击利用的机会就少一些,但是也无法避免被攻击
- UDP缺点:不可靠,不稳定因为没有TCP的这些机制,UDP在传输数据时,如果网络质量不好,就会很容易丢包,造成数据的缺失。
3、TCP UDP适用场景
- TCP:传输一些对信号完整性,信号质量有要求的信息。
- UDP:对网络通讯质量要求不高时,要求网络通讯速度要快的场景。
4、 TCP为什么是可靠连接?
- 因为tcp传输的数据满足3大条件,不丢失,不重复,按顺序到达。
5、OSI典型网络模型,简单说说有哪些
- ICMP协议是一个网络层协议。
一个新搭建好的网络,往往需要先进行一个简单的测试,来验证网络是否畅通;但是IP协议并不提供可靠传输。如果丢包了,IP协议并不能通知传输层是否丢包以及丢包的原因。所以我们就需要一种协议来完成这样的功能–ICMP协议。 - ARP:地址解析协议(Address Resolution Protocol)
- 基本功能:知道目标设备的IP地址,查询目标设备的MAC地址,以保证通信的顺利进行。
- 它是IPv4中网络层必不可少的协议,不过在IPv6中已不再适用,并被邻居发现协议(NDP)所替代RARP:是将MAC物理地址转换成IP地址。
linux网络编程大杂烩==Linux应用编程7相关推荐
- linux 网络使用log,linux 网络命令last、lastlog、traceroute、netstat
last /usr/bin/last 语法:last 功能:列出目前与过去登入系统的用户信息 reboot 是重启信息 lastlog lastlog -u 502(用户ID) traceroute ...
- linux 网络端口状态,Linux下用netstat查看网络状态、端口状态(转)
转:http://blog.csdn.net/guodongdongnumber1/article/details/11383019 在linux一般使用netstat 来查看系统端口使用情况步. n ...
- linux 虚拟机大量udp请求失败_理解 Linux 网络栈:Linux 网络协议栈简单总结分析...
1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...
- 理解 Linux 网络栈:Linux 网络协议栈简单总结
1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...
- linux网络驱动架构,Linux网络体系架构和网卡驱动设计
Linux网络体系架构 1.Linux的协议栈层次 2.Linux的网络子系统架构 Linux的协议栈层次 Linux的优点之一在于它丰富而稳定的网络协议栈.其范围从协议无关层(例如通用socket层 ...
- linux网络共享文件夹,[Linux] - Windows与Linux网络共享文件夹挂载方法
Windows与Linux网络SMB方式文件夹共享挂载 本示例系统: Windows 2003+ Linux-Centos/Ubuntu 本示例全为命令行操作,如何使用Windows.Linux命令行 ...
- linux 网络函数调用链,Linux通知链机制及实例
Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,要使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.内核实现了事件通知链机制(notification cha ...
- linux网络流量统计,linux下网络流量监控统计
最近在做虚拟化迁入评估,其中很重要的一项就是流量的问题.现在部署一个工具和脚本用来统计服务器的网络流量. linux下监控流量的工具有很多,比如ifstat.iftop等. 个人还是喜欢ifstat, ...
- kali linux 网络架构,Kali Linux网络扫描教程大学霸内部资料
Kali Linux网络扫描教程大学霸内部资料 Kali Linux网络扫描教程大学霸内部资料 黑白教程:95元 彩色教程:118元 介绍:渗透测试是一门操作性极强的学科.掌握该技能的最佳方式就是大量 ...
最新文章
- char和uchar区别
- 第十周项目3-血型统计
- Qt 从C ++定义QML类型(一)
- pyecharts 绘制地图
- 兔子--百度地图所需的jar+so下载地址
- mysql 开发包 安装_mysql的zip包的安装方法
- [转]如何删除图片链接的蓝色边框?
- Windows xp下IDT Hook和GDT的学习
- 获取对象的接口信息(方法/属性/事件)(VB6代码)
- bzoj 3101: N皇后
- python-pycharm使用方法
- aspose转pdf乱码问题
- mysql配置文件路径
- 疯狂的程序员 21-30
- process.start打开后没有界面_越狱后安装这些美化插件,让手机变好看
- 【小月电子】ALTERA FPGA开发板系统学习教程-LESSON9简易测试系统
- mysql 中 一个汉字吗_MySQL 中一个汉字占多少存储?
- 使用Mysql Navcat导出查询数据excel时出现数据丢失
- 关于软件的一些哲学思考(四)软件基本要素 四要素
- java跳出循环的几种方式