6 网络

news2024/9/8 23:22:40

6 网络

  • 1、概念
  • 2 IP地址
  • 3、套接字
  • 4、TCP协议
    • 4.1 TCP协议的基本特征
    • 4.2 建立连接
    • 4.4 终止连接
    • 4.5 编程模型
  • 5、UDP协议
    • 5.1 UDP协议的基本特性
    • 5.2 常用函数
    • 5.3 UDP通信模型
  • 6、域名解析

1、概念

计算机网络是实现资源共享和信息传递的计算机系统
ISO/OSI网络协议模型
在这里插入图片描述

TCP/IP协议
在这里插入图片描述

·应用程序负责组织的通常都是与业务相关的数据内容,而要想把这些数据内容通过网络发送出去,就要将其自上向下地压入协议栈,每经历一个协议层,就会对数据做一层封包,每一层输出的封包都是下一层输入的内容,消息包沿着协议栈的运动形成了消息流。
·当从网络上接收数据时,过程刚好相反,消息包自下向上地流经协议栈,每经历一个协议层,就会对输入的数据解一层封包,经过层层解包以后,应用程序最终得到的将只是与业务相关的数据内容

2 IP地址

  • 什么是P地址?
    IP地址,是IP协议提供的一种统一的地址格式,为互联网上的每个网络和每台主机分配一个逻辑地址,借以消除物理地址所带来的差异性
  • IP地址如何表示?
    在计算机内部,IP地址用一个32位无符号整数表示,如:0x01020304。
    人们更习惯使用点分十进制字符串表示,如:1.2.3.4。字符串形式的从左到右,对应整数形式的从高字节到低字节。注意这里所说的高低指的是数位高低而非地址高低
  • 什么是IP地址分级?
    A级地址:以0为首的8位网络地址+24位本地地址
    B级地址:以10为首的16位网络地址+16位本地地址
    C级地址:以110为首的24位网络地址+8位本地地址
    D级地址:以1110为首的32位多播地址
    例如:某台计算机的IP地址:192.168.182.48,写成整数形式:11000000 10101000 10110110 00110000
    代表的是C级地址,网络地址:192.168.182.0,本地地址:48
  • 子网掩码
    • 借助子网掩码可以快速帮助我们区定IP地址的网络地址和本地地址
      • 以IP地址:192.168.182.48,子网掩码:255.255.255.0为例
        网络地址=IP地址&子网掩码
        192.168.182.48 & 255.255.255.0 = 192.168.182.0
        本地地址=IP地址&~子网掩码
        192.168.182.48 & 0.0.0.255 = 0.0.0.48

3、套接字

在这里插入图片描述

套接字代表着主机的通信能力
套接字接口库规定在网络传输过程中采用网络字节序,也就是大端字节序,
而本机数据可能是小短字节序
- 小端字节序:数据的低位存放在低地址
- 大端字节序:数据的低位存放在高地址

4、TCP协议

TCP提供客户机与服务器的连接

4.1 TCP协议的基本特征

一个完整TCP通信过程需要依次经历三个阶段

  • 首先,客户机必须建立与服务器的连接
  • 然后,凭借已建立好的连接,通信双方相互交换数据
  • 最后,客户机与服务器双双终止连接,结束通信过程
    TCP保证数据传输的可靠性
  • TCP的协议栈底层在向另一端发送数据时,会要求对方在一个给定的时间窗口内返回确认。如果超过了这个时间窗口仍没有收到确认,则TCP会重传数据并等待更长的时间。只有在数次重传均告失败以后,TCP才会最终放弃。TCP含有用于动态估算数据往返时间(Round-Trip Time,RTT)的算法,因此它知道等待一个确认需要多长时间
    TCP保证数据传输的有序性
  • TCP的协议栈底层在向另一端发送数据时,会为所发送数据的每个字节指定一个序列号。即使这些数据字节没有能够按照发送时的顺序到达接收方,接收方的TCP也可以根据它们的序列号重新排序,再把最后的结果交给应用程序
    TCP是全双工的
  • 在给定的连接上,应用程序在任何时候都既可以发送数据也可以接收数据。因此,TCP必须跟踪每个方向上数据流的状态信息,如序列号和通告窗口的大小

4.2 建立连接

三路握手

  • 客户机的TCP协议栈向服务器发送一个SYN分节,告知对方自己将在连接中发送数据的初始序列号
  • 服务器的TCP协议栈向客户机发送一个单个分节,其中不仅包括对客户机SYN分节的ACK应答,还包含服务器自己的SYN分节,以告知对方自己在同一连接中发送数据的初始序列号
  • 客户机的TCP协议栈向服务返回ACK应答,以表示对服务器所发SYN的确认
    在这里插入图片描述

tcp包头结构,有20个字节,其中2个字节的源端口、2个字节的目的端口、4字节的序号、4字节的确认号等等共计20个字节的数据
在这里插入图片描述

三次握手的解释:
① 客户机首先向服务器发送数据包,数据包中的SYN的比特位是1,并且在序号位置指定一个数字,假定为100
② 服务器收到客户机发来的数据包,其中SYN的比特位是1,那么服务器就会应答一个数据包,数据包里的ACK比特位置1,代表一种应答,并且在确认号这里会将收到的序号+1,这里是101,代表服务器真的收到了客户机的数据包,然后将序号指定一个数字假定是200,并且将SYN比特位置1,一起发送给客户机
③ 客户机收到服务器发来的数据包,首先检查数据包中的ACK和确认号是否正确,然后会向服务器应答一个数据包,其中ACK比特位置1,代表是对服务器的应答,确认号填写收到的序号+1,这里是201,发送给服务器,代表客户机真的收到了服务器的数据包
④ 服务器收到数据包,检查ACK和确认号,至此连接建立

接口## 4.3 交换数据

  • 一旦连接建立,客户机即可构造请求包并发往服务器,服务器接收并处理来自客户机的请求包,构造响应包
  • 服务器向客户机发送响应包,同时捎带对客户机请求包的ACK应答。
  • 客户机接收来自服务器的响应包,同时向对方发送ACK应答
    在这里插入图片描述

4.4 终止连接

四次挥手

  • 客户机或者服务器主动关闭连接,TCP协议栈向对方发送FIN分节,表示数据通信结束。如果此时尚有数据滞留于发送缓冲区中,则FIN分节跟在所有未发送数据之后
  • 接收到FIN分节的另一端执行被动关闭,-方面通过TCP协议栈向对方发送ACK应答,另一方面向应用程序传递文件结束符
  • 一段时间以后,方才接收到FIN分节的进程关闭自己的连接,同时通过TCP协议栈向对方发送FIN分节
  • 对方在收到FIN分节后发送ACK应答
    四次挥手的解释
    ① 客户机关闭套接字之后,客户机首先向服务器发送一个数据包,其中FIN比特位置1
    ② 服务器收到客户机发来的数据包,其中FIN比特位为1,向客户机回传一个应答,其中ACK置1
    ③ 服务器关闭对应的套接字操作之后,服务器向客户机发送一个数据包,其中FIN比特位置1
    ④ 客户机收到服务器发来的数据包,其中的FIN比特位为1,向服务器回传一个应答,其中ACK置1
    ⑤ 至此连接断开,通信终止

4.5 编程模型

在这里插入图片描述

  • 相关函数
    1:socket 创建套接字
// 头文件 sys/socket.h
int socket(int domain,int type,int protocol);
- 功能:创建套接字
- 参数:
	- domain:通信域,协议族,可取以下值:
		PF_LOCAL/PF_UNIX - 本地套接字,进程间通信
		PF_INET - 基于IPV4的网络通信
		PF_INET6 - 基于IPv6的网络通信
		PF_PACKET - 基于底层包的网络通信
	- type:套接字类型,可取以下值:
		SOCK_STREAM - 流式套接字,基于TCP协议
		SOCK_DGRAM - 数据报套接字,基于UDP协议
		SOCK_RAW - 原始套接字,工作在传输层以下
	- protocol:特殊协议,对于流式和数据报套接字而言,只能取0
- 返回值:成功返回表示套接字对象的文件描述符,失败返回-1

2:相关结构体

/*套接字接口库通过地址结构定位一个通信主体,可以是一个文件,可以是一台远程主机,也可以是执行者自己 */
// 基本地址结构,本身没有实际意义,仅用于泛型化参数
struct sockaddr{
	sa_family_t sa_family; // 地址族
	char sa_data\[14\]; // 地址值
}
// 本地地址结构,用于AF_LOCAL/AF_UNIX域的本地通信
struct sockaddr_un{
	sa_family_t sun_family;// 地址族(AF_LOCAL/AF_UNIX)
	char sun_path\[\];// 本地套接字文件的路径
}
// 网络地址结构,用于AF_INET域的IPV4写径通信
struct sockaddr_in{
	sa_family_t sin_family;∥地址族(AF_INET)
	in_port_t sin_port; //端口号(0~65535) - unsigned short
	struct in_addr sin_addr;//IP地址 - unsigned int
}
// 网络地址结构,用于AF_INET域的IPV4网络通信
struct in_addr{
	in_addr_t s_addr;
}
typedef uint16_t in_port_t; //无符号16位整数
typedef uint32_t in_addr_t; //无符号32位整数

3:字节序转换函数

uint32_t htonl(uint32_t hostlong); //长整形主机字节序到网络字节序
uint32_t ntohl(uint32_t netllong); //长整形网络字节序到主机字节序
uint16_t htons(uint16_t hostshort); //短整形主机字节序到网络字节序
uint16_t ntohs(uint16_t netshort); //短整型网络字节序到主机字节序
in_addr_t inet_addr(char const* ip); // 点分十进制字符串地址 -> 网络字节序形式整数地址
int inet_aton(char const* ip,struct in_addr* nip); //点分十进制字符串地址 -> 网络字节序形式整数地址
char* inet_ntoa(struct in_addr nip); //网络字节序形式整数地址 -> 点分十进制字符串地址

4:bind 将套接字和本机的地址结构绑定在一起

// 头文件 sys/socket.h
int bind(int sockfd,struct sockaddr const* addr,socklen_t addrlen);
- 功能:将套接字和本机的地址结构绑定在一起
- 参数:
	- sockfd:套接字描述符。
	- addr:自己的地址结构。
	- addrlen:地址结构的字节数
- 返回值:成功返回0,失败返回-1

5:listen 启动侦听

// 头文件 sys/socket.h
int listen(int sockfd,int backlog)
- 功能:启动侦听:在指定套接字上启动对连接请求的侦听功能
- 参数:
	- sockfd:套接字描述符,在调用此函数之前是一个主动套接字,是不能感知连接请求的,在调用此函数并成功返回之后,是一个被动套接字,具有感知连接请求的能力。
	- backlog:未决连接请求队列的最大长度,一般取不小于1024的值。
- 返回值:成功返回0,失败返回-1

6:accept

// 头文件 sys/socket.h
int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);
- 功能:等待并接受连接请求,在指定套接字上阻塞,直到连接建立完成。
- 参数:
	- sockfd:侦听套接字描述符
	- addr:输出连接请求发起方的地址信息
	- addrlen:输出连接请求发起方的地址信息字节数
- 返回值:成功返回可用于后续通信的连接套接字描述符,失败返回-1
  • 案例
// tcp 服务器
#include <stdio.h>
#include <ctype.h> // toupper
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h> // 网络相关
#include <sys/types.h>// 网络相关
#include <arpa/inet.h>// 网络相关
#include <sys/wait.h>

// 收尸
void sigfun(int signum){
	printf("服务器:收尸\n");
	for(;;){
		pid_t pid = waitpid(-1,NULL,WNOHANG);
		if(pid == -1){
			if(errno == ECHILD){
				printf("没有子进程了\n");
				break;
			}else{
				perror("waitpid");
				return ;
			}
		}else if(pid == 0){
			printf("%d进程在运行\n",getpid());
			break;
		}else{
			printf("%d进程:回收了%d进程的僵尸\n",getpid(),pid);
		}
	}
}

int main(){
	printf("服务器设置信号量\n");
	if(signal(SIGCHLD,sigfun)==SIG_ERR){ // 对17号信号做捕获处理
		perror("signal");
		return -1;
	}
	printf("服务器:创建套接字\n");
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd == -1){
		perror("socket");
		return -1;
	}
	printf("服务器:组织地址结构\n");
	struct sockaddr_in ser;// IPV4的网络地址结构
	ser.sin_family = AF_INET;
	ser.sin_port = htons(8980);// 端口号,这里需要做字节序转换,因为TCP协议栈需要这个端口
	ser.sin_addr.s_addr = inet_addr("192.168.174.152");
	printf("服务器:绑定套接字和地址结构\n");
	if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)) == -1){
		perror("bind");
		return -1;
	}
	printf("服务器:启动侦听\n");
	if(listen(sockfd,1024)==-1){// 监听,用于接收客户端的连接请求(3次握手)
		perror("listen");
		return -1;
	}
	for(;;){
		printf("服务器:等待连接\n");
		struct sockaddr_in cli; //用于输出客户端的地址结构
		socklen_t len = sizeof(cli); // 用来输出地址结构的大小
		int conn = accept(sockfd,(struct sockaddr*)&cli,&len); // 用于完成与客户端的3次握手中的后两次
		if(conn == -1){ // conn 是用来和客户端通信用的,每接入一个客户端,就会生成一个新的conn
			perror("accept");
			return -1;
		}
		printf("服务器:接收到%s:%hu的客户端的连接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
		printf("服务器:业务处理\n");
		pid_t pid = fork();
		if(pid == -1){
			perror("fork");
			return -1;
		}
		if(pid == 0){
			close(sockfd);// 关掉从父进程复制过来的通信套接字
			for(;;){
				// 接收客户端发送的小写的串
				char buf[64]={};
				ssize_t size = read(conn,buf,sizeof(buf)-1);
				if(size == -1){
					perror("read");
					close(conn);
					return -1;
				}
				//客户端断开连接时
				if(size == 0){break;}
				// 转大写
				for(int i=0;i<strlen(buf);i++){
					buf[i]=toupper(buf[i]);
				}
				// 将大写的串回传给客户端
				if(write(conn,buf,strlen(buf))==-1){
					perror("write");
					close(conn);
					return -1;
				}
			}
			printf("服务器:关闭通信套接字\n");
			close(conn);
			return 0;
		}
		close(conn);// 子进程已经复制了这个套接字,父进程自己的直接关掉即可
	}
	printf("关闭服务器\n");
	close(sockfd);
	return 0;
}

7:connect 将套接字和对方的地址结构连接在一起

// 头文件 sys/socket.h
int connect(int sockfd,struct sockaddr const* addr,socklen_t addrlen);
- 功能:将套接字和对方的地址结构连接在一起
- 参数:
	- sockfd:套接字描述符
	- addr:对方的地址结构
	- addrlen:地址结构的字节数
- 返回值:成功返回0,失败返回-1

8:send 发送数据

// 头文件 sys/socket.h
ssize_t send(int sockfd,void const* buf,size_t count,int flags);
- 功能:发送数据
- 参数:
	- 若flags取0则与write函数完全等价,另外也可取以下值:
		MSG_DONTWAIT - 以非阻塞方式接收数据。
		MSG_OOB - 接收带外数据。
		MSG_DONTROUTE - 不查路由表,直接在本地网络中寻找目的主机
- 返回值:成功返回实际发送的字节数,失败返回-1

9:recv 接收数据

// 头文件 sys/socket.h
ssize_t recv(int sockfd,void* buf,size_t count,int flags);
- 功能:接收数据
- 参数:
	- 若flags取0则与read函数完全等价,另外也可取以下值:
		MSG_DONTWAIT - 以非阻塞方式接收数据。
		MSG_OOB - 接收带外数据。
		MSG_WAITALL - 等待所有数据,即不接收到count字节就不返回。
- 返回值:成功返回实际接收到的字节数,失败返回-1
  • 案例
// 基于tcp客户端的连接
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

int main(){
	printf("客户端:创建套接字\n");
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd == -1){
		perror("socket");
		return -1;
	}
	printf("客户端:组织服务器的地址结构\n");
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(8980);
	ser.sin_addr.s_addr = inet_addr("192.168.174.152");
	printf("客户端:发起连接\n");
	if(connect(sockfd,(struct sockaddr*)&ser,sizeof(ser))==-1){
		perror("connect");
		return -1;
	}
	printf("客户端:业务处理\n");
	for(;;){
		// 发送小写的串
		char buf[64]={};
		fgets(buf,sizeof(buf),stdin);
		if(strcmp(buf,"!\n")==0){
			break;
		}
		if(send(sockfd,buf,strlen(buf),0)==-1){
			perror("send");
			return -1;
		}
		// 接收大写的串
		if(recv(sockfd,buf,sizeof(buf)-1,0)==-1){
			perror("recv");
			return -1;
		}
		// 显示
		printf("%s",buf);
	}
	printf("客户端:关闭套接字\n");
	close(sockfd);
	return 0;
}

5、UDP协议

5.1 UDP协议的基本特性

  • UDP不提供客户机与服务器的连接
    • UDP的客户机与服务器不必存在长期关系。一个UDP的客户机在通过一个套接字向一个UDP服务器发送了一个数据报之后,马上可以通过同一个套接字向另一个UDP服务器发送另一个数据报。同样,一个UDP服务器也可以通过同一个套接字接收来自不同客户机的数据报
  • UDP不保证数据传输的可靠性和有序性
    • UDP的协议栈底层不提供诸如确认、超时重传、RTT估算以及序列号等机制。因此UDP数据报在网络传输的过程中,可能丢失,也可能重复,甚至重新排序。应用程序必须自己处理这些情况
  • UDP不提供流量控制
    • UDP的协议栈底层只是一味地按照发送方的速率发送数据,全然不顾接收方的缓冲区是否装得下
  • UDP是全双工的
    • 在一个UDP套接字上,应用程序在任何时候都既可以发送数据也可以接收数据

5.2 常用函数

1:recvfrom 从哪里接收数据

// 头文件 sys/socket.h
ssize_t recvfrom(int sockfd,void* buf,size_t count,int flags,struct sockaddr* src_addr,socklen_t* addrlen);
- 功能:从哪里接收数据
- 参数:
	- 前四个参数和函数recv相同
	- src_addr:输出源主机的地址信息
	- addrlen:输入输出源主机的地址信息的字节数。
- 返回值:成功返回实际接收的字节数,失败返回-1

2:sendto 发送数据到哪里

// 头文件 sys/socket.h
ssize_t sendto(int sockfd,void const* buf,size_t count,int flags,struct sockaddr const* dest_addr,socklen_t addrlen);
- 功能:发送数据到哪里
- 参数:
	- 前四个参数和函数send相同
	- dest_addr:目的主机的地址信息。
	- addrlen:目的主机的地址信息的字节数。
- 返回值:成功返回实际发送的字节数,失败返回-1

5.3 UDP通信模型

在这里插入图片描述

  • 服务器
// udp 服务器
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys//types.h>
#include <arpa/inet.h>

int main(){
	printf("服务器:创建套接字\n");
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd == -1){
		perror("socket");
		return -1;
	}
	printf("服务器:组织地址结构\n");
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(8090);
	ser.sin_addr.s_addr=inet_addr("192.168.174.152");
	printf("服务器:绑定套接字和地址结构\n");
	if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser))==-1){
		perror("bind");
		return -1;
	}
	printf("服务器:业务处理\n");
	for(;;){
		char buf[64]={};
		struct sockaddr_in cli;
		socklen_t len = sizeof(cli);
		if(recvfrom(sockfd,buf,sizeof(buf)-1,0,(struct sockaddr*)&cli,&len)==-1){
			perror("recvfrom");
			return -1;
		}
		// 转大写
		for(int i=0;i<strlen(buf);i++){
			buf[i] = toupper(buf[i]);
		}
		// 将大写的串回传到客户端
		if(sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*) &cli,len) == -1){
			perror("sendto");
			return -1;
		}
	}
	printf("服务器关闭套接字\n");
	close(sockfd);
	return 0;
}
  • 客户端
// UDP客户端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(){
	printf("客户端:创建套接字\n");
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd == -1){
		perror("socker");
		return -1;
	}        
	printf("客户端:组织服务器地址结构\n");
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(8090);
	ser.sin_addr.s_addr = inet_addr("192.168.174.152");
	printf("客户端:业务处理\n");
	for(;;){
		// 向客户端发送小写的串
		char buf[64] = {};
		fgets(buf,sizeof(buf),stdin);
		if(strcmp(buf,"!\n")==0){
				break;
		}
		if(sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser,sizeof(ser))==-1){
				perror("sendto");
				return -1;
		}
		// 接收服务器回传
		if(recv(sockfd,buf,sizeof(buf)-1,0)==-1){
				perror("recv");
				return -1;
		}
		// 显示
		printf("客户端:收到%s",buf);
	}
	// 关闭套接字
	close(sockfd);
	return 0;
}

6、域名解析

  • IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替1P地址标识站点地址
  • 域名解析就是域名到IP地址的转换过程。域名的解析工作由DNS服务器完成
  • 当应用过程需要将一个主机域名映P地址时,就调用域名解析函数,解析函数将待转换的域名放在DNS请求中,以UDP报文方式发给本地域名服务器。本地的域名服务器查到域名后,将对应的IP地址放在应答报文中返回。
    相关函数
    gethostbyname 获取主机信息
// 头文件 netdb.h
struct hostent* gethostbyname(char const* host_name);
- 功能:通过参数所传的主机域名,获取主机信息
- 参数:
	- host_name 主机域名
- 返回值:函数执行成功返回表示主机信息的结构体指针,失败返回NULL
- 注意,该函数需要再联网情况下使用

结构

struct hostent{
	char *h_name; //主机官方名
	char **h_aliases; //主机别名表
	int h_addrtype; //地址类型
	int h_length; //地址长度
	char **h_addr_list; //IP地址表
};
  • 案例
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc,char* argv[]){
	struct hostent* h = gethostbyname(argv[1]);
	if(h==NULL){
		perror("gethostbyname");
		return -1;
	}
	printf("主机官方名\n");
	printf("\t%s\n",h->h_name);
	printf("主机别名\n");
	for(char **pp = h->h_aliases;*pp;pp++){
		printf("\t%s\n",*pp);
	}
	printf("IP地址表\n");
	for(struct in_addr **pp=(struct in_addr**)h->h_addr_list;*pp;pp++){
		printf("\t%s\n",inet_ntoa(**pp));
	}
	return 0;
}
  • 创建http请求发送
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

int main(){
	// 创建套接字
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd == -1){
		perror("socket");
		return -1;
	}
	// 组织百度服务器的地址结构
	struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(80);
	ser.sin_addr.s_addr = inet_addr("36.155.132.76");
	// 向百度服务器发起连接
	if(connect(sockfd,(struct sockaddr*)&ser,sizeof(ser))==-1){
		perror("connect");
		return -1;
	}
	// 组织http请求并发送给百度服务器
	char request[1024] ={};
	sprintf(request,"GET / HTTP/1.1\r\n"
					"Host: www.baidu.com\r\n"
					"Accept: */*\r\n"
					"Connection: close\r\n\r\n");
	if(send(sockfd,request,strlen(request),0)==-1){
		perror("send");
		return -1;
	}
	// 接收百度服务器回传的响应
	for(;;){
		char respond[1024] = {};
		ssize_t size = recv(sockfd,respond,sizeof(respond)-1,0);
		if(size == -1){
			perror("recv");
			return -1;
		}
		if(size == 0){
			break;
		}
		printf("%s",respond);
	}
	printf("\n");
	close(sockfd);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1957815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

应急响应靶场

靶场搭建 靶场环境搭建&#xff1a;首先确定目标靶机的IP地址&#xff1a; 端口探测&#xff1a;发现只开放了22号端口 尝试利用hydra进行爆破&#xff1a; 成功找到了密码。ssh远程登录之后&#xff0c;添加后门账号: msfvenom生成msf的木马&#xff1a; 利用python快速搭建h…

代码随想录 day 25 回溯

第七章 回溯算法 part04 491.递增子序列 本题和大家刚做过的 90.子集II 非常像&#xff0c;但又很不一样&#xff0c;很容易掉坑里。 https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 视频讲解&#xff1a;https://www.bilibili.com/vi…

培训第十六天(web服务apache与nginx)

上午 静态资源 根据开发者保存在项目资源目录中的路径访问静态资源html 图片 js css 音乐 视频 f12&#xff0c;开发者工具&#xff0c;网络 1、web基本概念 web服务器&#xff08;web server&#xff09;&#xff1a;也称HTTP服务器&#xff08;HTTP server&#xff09;&am…

解决Windows密码丢失问题:详细指南

解决Windows密码丢失问题&#xff1a;详细指南 引言 最近因为某些工作缘故&#xff0c;接触到windows比较频繁&#xff0c;特此记录一下 当下&#xff0c;计算机安全是每个人都不能忽视的重要问题。然而&#xff0c;有时可能因为忘记密码而无法访问自己的Windows系统&#xf…

NAS、SAN 与 DAS 的比较与应用场景

文章目录 1. NAS&#xff08;网络附加存储&#xff09;定义特点实现成本&#xff1a;适用场景 2. SAN&#xff08;存储区域网络&#xff09;定义特点实现成本&#xff1a;适用场景 3. DAS&#xff08;直接附加存储&#xff09;定义特点实现成本&#xff1a;适用场景 区别总结结…

基于tkinter的学生信息管理系统之登录界面和主界面菜单设计

目录 一、tkinter的介绍 二、登陆界面的设计 1、登陆界面完整代码 2、部分代码讲解 3、登录的数据模型设计 4、效果展示 三、学生主界面菜单设计 1、学生主界面菜单设计完整代码 2、 部分代码讲解 3、效果展示 四、数据库的模型设计 欢迎大家进来学习和支持&#xff01…

文件操作相关的精讲

目录&#xff1a; 思维导图 一. 文件定义 二. 文件的打开和关闭 三. 文件的顺序读写操作 四. 文件的随机读写操作 五. 文本文件和二进制文件 六. 文件读取结束的判断 七.文件缓冲区 思维导图&#xff1a; 一. 文件定义 1.文件定义 C语言中&#xff0c;文件是指一组相…

Chapter 18 Python异常

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、什么是异常二、捕获异常三、异常的传递 前言 在Python中&#xff0c;异常是一种特定的对象&#xff0c;能够在程序运行过程中被抛出和处理。有效地管理异常不仅可以…

Spark+实例解读

第一部分 Spark入门 学习教程&#xff1a;Spark 教程 | Spark 教程 Spark 集成了许多大数据工具&#xff0c;例如 Spark 可以处理任何 Hadoop 数据源&#xff0c;也能在 Hadoop 集群上执行。大数据业内有个共识认为&#xff0c;Spark 只是Hadoop MapReduce 的扩展&#xff08…

精准客户从何而来?一招让你的客户源源不断!

你们是否还在为找不到精准客户而烦恼&#xff1f; 今天&#xff0c;我要分享一招非常实用的技巧&#xff0c;让你也能拥有源源不断的客源&#xff01; 首先&#xff0c;我们需要深入了解自己的目标客户。他们是谁&#xff1f;他们的需求是什么&#xff1f;并利用大数据洞察客…

Cocos Creator文档学习记录

Cocos Creator文档学习记录 一、什么是Cocos Creator 官方文档链接&#xff1a;Hello World | Cocos Creator 百度百科&#xff1a;Cocos Creator_百度百科 Cocos Creator包括开发和调试、商业化 SDK 的集成、多平台发布、测试、上线这一整套工作流程&#xff0c;可多次的迭…

【前端 19】使用Vue-CLI脚手架构建Vue2项目

使用Vue CLI构建Vue 2项目 引言 Vue.js 是一个构建用户界面的渐进式JavaScript框架&#xff0c;以其轻量级和易用性受到前端开发者的广泛喜爱。Vue CLI&#xff08;Vue Command Line Interface&#xff09;是一个基于Vue.js进行快速开发的完整系统&#xff0c;提供了零配置的项…

Amazon Bedrock + Amazon DynamoDB 数据设计与建模

一、Amazon DynamoDB简介 在当今数字化转型的浪潮中&#xff0c;企业对数据处理能力的需求日益增长&#xff0c;为了应对大规模数据和高并发访问的挑战&#xff0c;选择一款合适的数据库解决方案变得尤为重要。 Amazon DynamoDB&#xff0c;作为亚马逊云科技提供的一种完全托…

【人工智能】Transformers之Pipeline(六):图像分类(image-classification)

目录 一、引言 二、图像分类&#xff08;image-classification&#xff09; 2.1 概述 2.2 技术原理 2.3 应用场景 2.4 pipeline参数 2.4.1 pipeline对象实例化参数 2.4.2 pipeline对象使用参数 2.4 pipeline实战 2.5 模型排名 三、总结 一、引言 pipeline&#x…

文远知行IPO,L4的梦还是L2给的

文&#xff5c;刘俊宏 编&#xff5c;王一粟 随着萝卜快跑在武汉初步验证了Robotaxi商业闭环&#xff0c;L4自动驾驶的公司们终于迎来了“黎明的曙光”。 7月27日&#xff0c;文远知行向美国SEC&#xff08;证券交易委员会&#xff09;提交了招股书&#xff0c;以超越Moment…

Flask Bootstrap #2 - MVC架构

Reference https://medium.com/%E5%B7%A5%E7%A8%8B%E9%9A%A8%E5%AF%AB%E7%AD%86%E8%A8%98/%E4%BD%BF%E7%94%A8-python-flask-%E5%BB%BA%E7%AB%8B%E7%B6%B2%E7%AB%99-353e449a9bc8 1 MVC架构 在 Flask Boostrap #1 - 安装Flask 透过 app.route() 建立路由是 flask API 常见的…

实验2-4-1 求1到N的和*--sum记得累加啊!

//实验2-4-1 求1到N的和//计算序列 1 2 3 ... 的前N项之和。#include<stdio.h> #include<math.h> int main(){int N,sum0;scanf("%d",&N);for(int a1;a<N;a){ suma;//sum进行累加&#xff01;&#xff01;&#xff01;&#xff01;&#xff01…

VS2019编译和使用gtest测试(C++)

目录 一、首先下载gtest开源 二、使用gtest 一、首先下载gtest开源 https://pan.baidu.com/s/15m62KAJ29vNe1mrmAcmehA 提取码&#xff1a;vfxz 下载下来解压到文件夹&#xff0c;再在文件夹里面新建一个build文件夹&#xff0c;如下&#xff1a; 再安装cmake&#xff0c;…

Cocos Creator2D游戏开发(6)-飞机大战(4)-敌机产生

敌机产生&玩家发射子弹 敌机产生: 创建一个空节点 创建一个敌机预制体 把敌机图片拖入预制体内 使用代码生成敌机 让敌机动起来 创建一个预制体enemy_prefab双击预制体enemy_prefab,然后拖入一个敌机图片,设置好方向和尺寸,一定要记得保存然后关闭(场景编辑器里面的保存)…

【前端 18】安装Node.js

Node.js 安装指南 在今天的博客中&#xff0c;我们将一起探讨如何在您的计算机上安装Node.js。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;它允许你在服务器端运行 JavaScript 代码。无论您是前端开发者希望探索全栈开发&#xff0c;还是后端开发者寻…