socket编程,为何第二个recv出错?

时间:2022-01-12 11:26:50
#include <stdio.h>
#include <string> 
#include <winsock.h>
#include <winsock2.h>
#include <iostream> 
#define MAXLINE 10000
#define SA struct sockaddr
#define SOCKET int
 
using namespace std; 
int main (int argc,char * argv[]) 
{
    
     string s1,s2,s3,s4;
     cin>>s1>>s2>>s3>>s4; 
     SOCKET sockfd;
     char recvline[MAXLINE+1];
     WSADATA wsaData;
     if (WSAStartup(MAKEWORD(2,1),&wsaData)!=0)
     {
        perror("initial error!"); 
        WSACleanup(); 
        exit(1);
     } 
    
     struct sockaddr_in server_addr;
     struct hostent *hp;
     hp=(struct hostent *)malloc(sizeof(struct hostent));
     hp=gethostbyname("www.baidu.com");
     server_addr.sin_family=AF_INET; 
     server_addr.sin_port=htons(80);  
     memcpy((char*)&server_addr.sin_addr,(char*)hp->h_addr,hp->h_length); 
      
        
     if ((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)/*判断socket是否出错*/
     {
        perror("socket error");                                        
        exit(1);
     }
     
    
     
    if(connect(sockfd,(SA*)&server_addr,sizeof(server_addr))<0) //连接socket 
    {
        perror("connection error!");
        exit(1);
    }
    
     string strkey=(string)"GET /s?wd="+s2+(string)"&cl=3 HTTP/1.1<br />"
     "Accept: */*<br />" 
     "Referer:  http://www.baidu.com/<br />"
     "Accept-Language: zh-cn<br />"
     "Accept-Encoding: gzip, deflate<br />"
     "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)<br />"
     "Host: www.baidu.com<br />"
     "Connection: Keep-Alive<br />";
     const char* ptrkey =strkey.c_str(); 
     char bufferkey[2048];
     for (int i=0;bufferkey[i++]=*ptrkey++;);
    
     if(send(sockfd,bufferkey,sizeof(bufferkey),0)<0) //发送关键字 
     {
        perror("send error!");
        exit(1);
     } 
     
     if(recv(sockfd,recvline,MAXLINE,0)<0) //搜索结果返回 
      {
         perror("recv error!");
         exit(1);
      } 
  
     string strclick= (string)"GET /w.gif?query="+s2+(string)"&e=959f"/*&e=?不知道怎么处理*/+(string)"&title="+s4+(string)"&url=http%3A//www.rfidinfo.com.cn/Portal/Simple/"
     "Contact_4209.html&spos=4&path=http://www.baidu.com/s?ie=gb2312&bs=rfid&sr=&z=&cl=3&f=8&wd=rfid+"
     "%D0%C5%B4%EF%BB%E3%B4%CF&ct=0&t=1177206870437" /*url怎么处理?*/+
     (string)"HTTP/1.1\nAccept: */*\nReferer: http://www.baidu.com/s?wd="+s2+(string)"&cl=3\nAccept-Language: zh-cn\n"
     "Accept-Encoding: gzip, deflate\n"
     "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\n" 
     "Host: s.baidu.com\n"
     "Connection: Keep-Alive\n" ;
     const char* ptrclick =strkey.c_str(); 
     char bufferclick[2048];
     for (int i=0;bufferclick[i++]=*ptrclick++;); 
     
     if(send(sockfd,bufferclick,sizeof(bufferclick),0)<0) //点击搜索结果 
      { 
        perror("send error!");
        exit(1);
      }  
      
      if(recv(sockfd,recvline,MAXLINE,0)<0)  //返回点击内容 
      {
         perror("recv error!");
         exit(1);
      } 
      
     closesocket(sockfd);
     free(hp);
     WSACleanup();
     exit(0); 
}

12 个解决方案

#1


mark

#2


send时也无法发送get语句 是什么原因?

#3


不明白为什么要放到C++版面,全是C风格

#4


这个是用dev c++ 编的 要放c版么?

#5


第一次发送/接收数据后,需要关闭socket
第二次应该重新建立socket,然后发送/接收,
如此反复,连绵不绝。。。。。。。

#6


那就是说发送一次新建一次socket?不对吧?

#7


在HTTP协议里是这样的!
服务器已经close了!不信你可以试试看!
在第二次send之前sleep(15)
在sleep是,打开另一个终端窗口用netstat看连接情况连接应该是处在 CLOSE_WAIT状态,这个状态的意思就是对方已经关闭,系统正在等待应用程序调用close以结束这个连接,这也就是CLOSE_WAIT这个状态的由来!

#8


那你的意思是要从 
     WSADATA wsaData;
     if (WSAStartup(MAKEWORD(2,1),&wsaData)!=0)
     {
        perror("initial error!"); 
        WSACleanup(); 
        exit(1);
     }
开始做么?

#9


从 socket() 到 closesocket()

#10


还是不行 根本向百度发不出get请求

#11


发送的请求最后需要"\r\n\r\n"
以下是我改过的程序可以收到回应

#include <cerrno>
#include <string> 
#include <iostream>
#include <fstream>
#include <winsock.h>

using namespace std; 

#define CRLF2 "\r\n\r\n"
#define CRLF "\r\n"
#define CR "\r"
#define LF "\n"

#define MAX_RECV_LEN 40960
#define SA struct sockaddr
#define SOCKET int
 
int main (int argc,char * argv[]) 
{
SOCKET sockfd;
WSADATA wsaData;
struct sockaddr_in server_addr;
struct hostent *hp;

string strSend;
string strRecv;
char bufRecv[MAX_RECV_LEN + 1];

ofstream fout;
size_t posHtml;

int nSend, nRecv;

if (WSAStartup(MAKEWORD(2,1),&wsaData)!=0)
{
perror("initial error!"); 
WSACleanup(); 
exit(1);


hp=gethostbyname("www.baidu.com");
server_addr.sin_family=AF_INET; 
server_addr.sin_port=htons(80);  
memcpy((char*)&server_addr.sin_addr,(char*)hp->h_addr,hp->h_length); 
        
if ( (sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0 )
{
perror("socket()");                                        
exit(1);
}

    if( connect(sockfd,(SA*)&server_addr, sizeof(server_addr)) <0 )
    {
        perror("connect()");
        exit(1);
    }

string s;
    
strSend = "GET /s?wd=" "rfid" "&cl=3 HTTP/1.1"  CRLF  CRLF;

if( (nSend = send(sockfd, strSend.c_str(), strSend.length() ,0)) <0 )
{
perror("send()");
exit(1);


Sleep(5000);
bufRecv[0] = '\0';
if  ( (nRecv = recv(sockfd + 1, bufRecv, MAX_RECV_LEN, 0)) < 0 )
{
perror("recv()");
exit(1);
}

bufRecv[nRecv] = '\0';
strRecv = bufRecv;

if ( (strRecv.length() > 0)
&& ( (posHtml = strRecv.find(CRLF2)) != string::npos)
)
{
posHtml += 4;
fout.open("html.log", ios::out | ios::binary | ios::trunc);
fout << strRecv;
fout.close();
system("start html.log");

fout.open("html.html", ios::out | ios::binary | ios::trunc);
fout << strRecv.substr(posHtml);
fout.close();
system("start html.html");
}

closesocket(sockfd);
WSACleanup();

return 0;
}

#12


if  ( (nRecv = recv(sockfd + 1, bufRecv, MAX_RECV_LEN, 0)) < 0 )
应该改为
if  ( (nRecv = recv(sockfd, bufRecv, MAX_RECV_LEN, 0)) < 0 )

#1


mark

#2


send时也无法发送get语句 是什么原因?

#3


不明白为什么要放到C++版面,全是C风格

#4


这个是用dev c++ 编的 要放c版么?

#5


第一次发送/接收数据后,需要关闭socket
第二次应该重新建立socket,然后发送/接收,
如此反复,连绵不绝。。。。。。。

#6


那就是说发送一次新建一次socket?不对吧?

#7


在HTTP协议里是这样的!
服务器已经close了!不信你可以试试看!
在第二次send之前sleep(15)
在sleep是,打开另一个终端窗口用netstat看连接情况连接应该是处在 CLOSE_WAIT状态,这个状态的意思就是对方已经关闭,系统正在等待应用程序调用close以结束这个连接,这也就是CLOSE_WAIT这个状态的由来!

#8


那你的意思是要从 
     WSADATA wsaData;
     if (WSAStartup(MAKEWORD(2,1),&wsaData)!=0)
     {
        perror("initial error!"); 
        WSACleanup(); 
        exit(1);
     }
开始做么?

#9


从 socket() 到 closesocket()

#10


还是不行 根本向百度发不出get请求

#11


发送的请求最后需要"\r\n\r\n"
以下是我改过的程序可以收到回应

#include <cerrno>
#include <string> 
#include <iostream>
#include <fstream>
#include <winsock.h>

using namespace std; 

#define CRLF2 "\r\n\r\n"
#define CRLF "\r\n"
#define CR "\r"
#define LF "\n"

#define MAX_RECV_LEN 40960
#define SA struct sockaddr
#define SOCKET int
 
int main (int argc,char * argv[]) 
{
SOCKET sockfd;
WSADATA wsaData;
struct sockaddr_in server_addr;
struct hostent *hp;

string strSend;
string strRecv;
char bufRecv[MAX_RECV_LEN + 1];

ofstream fout;
size_t posHtml;

int nSend, nRecv;

if (WSAStartup(MAKEWORD(2,1),&wsaData)!=0)
{
perror("initial error!"); 
WSACleanup(); 
exit(1);


hp=gethostbyname("www.baidu.com");
server_addr.sin_family=AF_INET; 
server_addr.sin_port=htons(80);  
memcpy((char*)&server_addr.sin_addr,(char*)hp->h_addr,hp->h_length); 
        
if ( (sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0 )
{
perror("socket()");                                        
exit(1);
}

    if( connect(sockfd,(SA*)&server_addr, sizeof(server_addr)) <0 )
    {
        perror("connect()");
        exit(1);
    }

string s;
    
strSend = "GET /s?wd=" "rfid" "&cl=3 HTTP/1.1"  CRLF  CRLF;

if( (nSend = send(sockfd, strSend.c_str(), strSend.length() ,0)) <0 )
{
perror("send()");
exit(1);


Sleep(5000);
bufRecv[0] = '\0';
if  ( (nRecv = recv(sockfd + 1, bufRecv, MAX_RECV_LEN, 0)) < 0 )
{
perror("recv()");
exit(1);
}

bufRecv[nRecv] = '\0';
strRecv = bufRecv;

if ( (strRecv.length() > 0)
&& ( (posHtml = strRecv.find(CRLF2)) != string::npos)
)
{
posHtml += 4;
fout.open("html.log", ios::out | ios::binary | ios::trunc);
fout << strRecv;
fout.close();
system("start html.log");

fout.open("html.html", ios::out | ios::binary | ios::trunc);
fout << strRecv.substr(posHtml);
fout.close();
system("start html.html");
}

closesocket(sockfd);
WSACleanup();

return 0;
}

#12


if  ( (nRecv = recv(sockfd + 1, bufRecv, MAX_RECV_LEN, 0)) < 0 )
应该改为
if  ( (nRecv = recv(sockfd, bufRecv, MAX_RECV_LEN, 0)) < 0 )