• http客户端如何写


    使用wireshark协助,设置网卡本地,设置过滤器:http && (ip.src == 192.168.1.80 && ip.dst == 192.168.1.81) || (ip.src == 192.168.1.81 && ip.dst == 192.168.1.80)。

    查看数据:

    接收数据:
    Content-Length:17364652代表所发的数据字节总数,在 后即是数据的开始处。
    数据为:LOAD为文件的魔术字 表示文件的一个唯一值,可以将分割的块聚在一起。

    时间

    有限搬代码:

    int Get_File(int sockfd,char *url,int filelength,char *filebuf)
    {
    	int count;
    	char range[32];
    	int i;
    	int ret = 0;
    	char *p = NULL;
    	int downOver=0;
    	int downlength=0,writeRet;
    	int p_file;
    	int s32TimeOut=5*1000;
    	fd_set rfds;
    	int nRecvBuf=64*1024;//设置为32K
    	struct timeval tv;
    	
    	count  = (filelength%MAX_RECV_SIZE)?(filelength/MAX_RECV_SIZE +1):(filelength/MAX_RECV_SIZE);
    
    	for(i=0;i<1;i++)
    	{
    		if((i == (count-1))&&(filelength%MAX_RECV_SIZE))
    			sprintf(range,"%d-%d",i*MAX_RECV_SIZE,filelength-1);
    		else
    			sprintf(range,"%d-%d",i*MAX_RECV_SIZE,(i+1)*MAX_RECV_SIZE-1);
    
    		Package_Url_Get_File(url,range);
    		printf("send = %s 
    ",g_buf_send);
    
    		Send(sockfd, g_buf_send, strlen(g_buf_send), 0);
    		Net_Http_GetResponseHeader(sockfd);
    		/*需改为提取http 返回协议头和协议体总长,然后定长接收*/
    		//setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)s32TimeOut,sizeof(s32TimeOut));
    		//setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char*)nRecvBuf,sizeof(nRecvBuf));
    		while(!downOver)
    		{
    re_recv:
    		      tv.tv_sec  = 5;
             	      tv.tv_usec = 0;
    	             FD_ZERO(&rfds);     //每次循环都要清空集合,否则不能检测描述符变化
                        FD_SET(sockfd, &rfds);     //添加描述符
    			memset(g_buf_recv,0x0,sizeof(g_buf_recv));		
    			switch (select(sockfd + 1, &rfds, NULL, NULL, &tv))
              	      {
                    		case 1:
    					{
    						usleep(100);
    						ret = Recv(sockfd,g_buf_recv,sizeof(g_buf_recv)-1,0);
    						s32TimeOut = 0;
    						printf("recv len = %d
    ", ret);
    						 if ( 0 > ret )
                     				   {
                      				           printf("recvfrom error
    ");
                        				    break;
                     				   }
    						 p=g_buf_recv;
    						 Write_File(p,"",ret);
    						 printf("strlen(p)=%d 
    ",strlen(p));
    						 if(ret > 0) downlength += ret;
    					        if(downlength >= filelength) downOver = 1;
    						 goto re_recv;
    						 
                    			}
    				case 0:
    					{
    						printf("timeout
    ");//再次轮询
    
                  			        s32TimeOut--;
                  			        if (s32TimeOut == 0)
                   			    	  {
                     				       printf("last timeout
    ");
                      				  }
                      				  break;
    					}
    				default:
                     		   printf("Failed to select
    ");//select错误,退出程序
    			}
    
    		}
    	}
    	return 0;
    }
    void Package_Url_Get_File(char *url, char *range)
    {
    	char buf_range[64];
    	memset(g_buf_send,0x0,sizeof(g_buf_send));		                                          
    	sprintf(g_buf_send, "GET %s",url);
    
    	
    	//HTTP/1.1
     前面需要一个空格
    	strcat(g_buf_send," HTTP/1.1
    ");
    	strcat(g_buf_send, "Host: ");
    	strcat(g_buf_send, IP);
    	strcat(g_buf_send, ":");
    	strcat(g_buf_send, PORT);
    	
    //	sprintf(buf_range, "
    Range: bytes=%s
    ",range);
    //	strcat(g_buf_send,buf_range);
    	strcat(g_buf_send,"
    Connection: Keep-Alive
    
    ");
    	
    
    }
    

      

    int Send(int sockfd, char *sendbuf, int len, int flags)
    {
    	int sendlen = 0;
    	int ret = -1;
    
    	while(sendlen < len)
    	{
    		ret = send(sockfd, sendbuf+sendlen, len-sendlen, flags); 
    		if(-1 == ret)
    		{
    			perror("send");
    			exit(EXIT_FAILURE);
    		}
    		else
    			sendlen += ret;
    
    	}
    
    	return 0;
    
    }
    

      

    int Recv(int  sockfd,  char *recvbuf, int  len,  int  flags)
    {
    	int recv_len;
    
    	if ((recv_len = recv(sockfd, recvbuf, len, flags)) < 0)
    	{
    		perror("recv error");
    		exit(EXIT_FAILURE);
    	}
    
    	return recv_len;
    }
    

      

    char* Net_Http_GetResponseHeader(int sockfd)
    {
    	char c = 0;
    	int nIndex = 0;
    	static char ResponseHeader[1024]={0};
    	int bEndResponse = 0;
    	while(!bEndResponse && nIndex < 1024)
    	{
    		recv(sockfd,&c,1,0);
    		ResponseHeader[nIndex++] = c;
    		if(nIndex >= 4)
    		{
    			if(ResponseHeader[0]!='H'&&ResponseHeader[1]!='T'
    				&&ResponseHeader[2]!='T'&&ResponseHeader[3]!='P')
    			{
    				printf("ResponseHeader error !
    ");
    				return NULL;
    			}
    			if(ResponseHeader[nIndex - 4] == '
    ' && ResponseHeader[nIndex - 3] == '
    '
    				&& ResponseHeader[nIndex - 2] == '
    ' && ResponseHeader[nIndex - 1] == '
    ')
    			bEndResponse = 1;
    		}
    	}
    	ResponseHeader[nIndex]=0;
    	printf("ResponseHeader:%s 
    ",ResponseHeader);
    	return ResponseHeader;
    	
    }
    

      

     假如要实现断点则只需要加入字段Range: bytes=%d-  (%d)是你需要开始下载的文件的起始字节数。

    1.在linux 在写代码过程中要注意写入文件时候,写入的字节数要是recv函数返回的值为准,不要使用strlen函数,在返回的包中,尽量先将包头过滤出来。

    2.在window下,打开文件函数fopen需要指定wb二进制方式打开,否则在windows下,fwrite函数写入数据时会加上回车符OX0D。

    3.在window下,调试时候,如果在调用fwrite函数写入,没有经过fclose,ctrl+c程序终止的话会造成最后一段数据没有真正写入到文件。

  • 相关阅读:
    [公链观点] BTC 1.0, ETH 2.0, EOS 3.0, Dapp, WASM, DOT, ADA, VNT
    [FAQ] chrome.runtime.onMessage 问题, Unchecked runtime.lastError: The message port closed before a response was received
    [FAQ] Composer, Content-Length mismatch
    [PHP] Laravel 依赖注入使用不当引起的内存溢出
    [PHP] 浅谈 Laravel auth:api 不同驱动 token 和 passport 的区别
    [PHP] 自定义 laravel/passport 的误区讲解
    [Tools] Kali Linux 高清屏扩大系统字体、BurpSuite、OpenVAS
    [NoSQL] 从模型关系看 Mongodb 的选择理由
    [quacker] Browser Extension to Clean Website ADs in Quasar BEX
    [FE] Quasar BEX 预览版指南
  • 原文地址:https://www.cnblogs.com/kernel-style/p/3336550.html
Copyright © 2020-2023  润新知