TCP/UDP的对比,粘包分包抓包,http协议
服务器端:
一、loop 127.0.0.1本地回环测试地址
二、tcp特点
面向连接、可靠传输、字节流
粘包问题:tcp流式套接字,数据与数据之间没有套接字,导致可能多次的数据粘到一起
解决方法:(1)规定一些数据与数据之间的间隔符号:\r 、\n。
(2)指定要发送的数据的长度。
(3)将数据打包:定义结构体
struct msg:int size,char data
struct msg data = {5,"1.txt"};
TCP | UDP |
面向连接 | 无连接 |
可靠传输 | 不可靠 |
字节流 | 数据报 |
三、
(1)send函数,用于将数据从套接字发送到连接的另一端,是网络的专用函数。
int send( SOCKET , const char FAR *buf, int len, int flags );
第一个参数指定发送端套接字描述符;
第二个参数指明一个存放应用程序要发送数据的缓冲区;
第三个参数指明实际要发送的数据的字节数;
第四个参数一般置0。
(2)recv函数用于从套接字接收数据,用法与send相似。
完整性:send 和 recv 可能不会一次性传输所有数据,尤其是对于较大的数据量。在发送和接收数据时,可能需要在应用层进行多次调用来保证数据的完整传输。
tcp传输文件内容:
客户端、服务器端:
#include <head.h>
int connect_server(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if (fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));//"50000"
if (connect(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("connect_server fail");
return fd;
}
//./cli 127.0.0.1 50000 filename
int main(int argc, const char *argv[])
{
if (argc != 4)
{
printf("usage: %s <ip> <port> <filename>\n",argv[0]);
return -1;
}
int fd = connect_server(argv[1],argv[2]);
if (fd < 0)
return -1;
int fd_s = open(argv[3],O_RDONLY);
if (fd_s < 0)
handle_error_ret("open fail");
//write(fd,argv[3],strlen(argv[3])+1);
write(fd,argv[3],strlen(argv[3]));
//方式1
//sleep(1);
//方式2
write(fd,"\r\n",2);
char buf[100] = {0};
int ret = 0;
while (1)
{
ret = read(fd_s,buf,sizeof(buf));
if (ret == 0)
break;
write(fd,buf,ret);
}
close(fd_s);
close(fd);
return 0;
}
#include <head.h>
int init_server(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if (fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));//"50000"
if (bind(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("bind fail");
if (listen(fd,5) < 0)
handle_error_ret("listen fail");
return fd;
}
//./ser 127.0.0.1 50000
int main(int argc, const char *argv[])
{
int ret = 0;
if (argc != 3)
{
printf("Usage: %s <ip> <port>\n",argv[0]);
return -1;
}
int listenfd = init_server(argv[1],argv[2]);
if (listenfd < 0)
return -1;
int connfd = 0;
if ((connfd = accept(listenfd,NULL,NULL)) < 0)
handle_error_ret("accept fail");
//读文件名
char buf[100] = {0};
FILE *fp = fdopen(connfd,"r");
if (fp == NULL)
handle_error_ret("fdopen fail");
fgets(buf,sizeof(buf),fp); //buf => 1.txt\r\n
buf[strlen(buf)-2] = '\0';
// ret = read(connfd,buf,sizeof(buf));
// printf("ret = %d buf = %s\n",ret, buf);
printf("buf = %s\n",buf);
int fd_d = open(buf,O_WRONLY|O_CREAT|O_TRUNC,0666);
if (fd_d < 0)
handle_error_ret("open fail");
while (1)
{
//ret = read(connfd,buf,sizeof(buf));
ret = fread(buf,1,sizeof(buf),fp);
printf("ret = %d buf1 = %s \n",ret,buf);
if (ret == 0)
break;
write(fd_d,buf,ret);
}
close(fd_d);
close(connfd);
return 0;
}
四、远程访问:
window系统打开命令行,ping一下linux系统的ip地址,检测是否能连接,telnet+ip进入到linux操作系统中。
wireshark抓包工具:检查传输的文件流
五、http协议:
HTTP(Hyper Text Transfer Protocol): 全称超文本传输协议,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP 是一种应用层协议,是基于 TCP/IP 通信协议来传递数据的,其中 HTTP1.0、HTTP1.1、HTTP2.0 均为 TCP 实现,HTTP3.0 基于 UDP 实现。现主流使用 HTTP1.0 和 HTTP3.0
协议: 为了使数据在网络上从源头到达目的,网络通信的参与方必须遵循相同的规则,这套规则称为协议,它最终体现为在网络上传输的数据包的格式。
通俗点讲,协议就是要保证网络通信的双方,能够互相对接上号。就像是两个人传递纸条通过互相指定的暗号,如果发送天亮了,表示可以打游戏了等等
注意: 当我们访问一些网页时,是显示通过 HTTPS 来进行通信的,并且当下大多数的网页都是通过 HTTPS 来进行通信的,因为 HTTPS 在 HTTP 的基础上做了一个加密的工作。
2. HTTP 协议的工作过程
当我们在浏览器输入一个网址,此时浏览器就会给对应的服务器发送一个 HTTP 请求,对应的服务器收到这个请求之后,经过计算处理,就会返回一个 HTTP 响应。并且当我们访问一个网站时,可能涉及不止一次的 HTTP 请求和响应的交互过程。
基础术语:
客户端: 主动发起网络请求的一端
服务器: 被动接收网络请求的一端
请求: 客户端给服务器发送的数据
响应: 服务器给客户端返回的数据
HTTP 协议的重要特点: 一发一收,一问一答
注意: 网络编程中,除了一发一收之外,还有其它的模式
多发一收:例如上传大文件
一发多收:例如看直播时,搜索一个词条可以得到多个视频源
多发多收:例如串流(steam link、moonlight 等等)