【转】socket提交http表单 [C++]

【http报文格式】:hiphotos.baidu.com_luosiyong_pic_item_35cc8501675a1032728da52f.jpg

【用牡丹园BBS做测试】:

首先查看BBS源代码:(右键分别在BBS不同的两个区域点击并查看源代码,得到如下结果)hiphotos.baidu.com_luosiyong_pic_item_2ba0cc1f85facbc4e1fe0b30.jpg

【找到HTML源码中相应的变量和表格提交的地址并用程序实现】:hiphotos.baidu.com_luosiyong_pic_item_c7becb368e1e9f000b55a93a.jpg

【成功的运行】:(当然经过了N次测试,同时还感谢Inkoo的大力支持)hiphotos.baidu.com_luosiyong_pic_item_6e869b862df2990f66096e02.jpg
hiphotos.baidu.com_luosiyong_pic_item_6a778a00bf14dcb6e850cd0c.jpg
hiphotos.baidu.com_luosiyong_pic_item_b3bdebca1023ec77f31fe70d.jpg

【程序源代码】:

/***************code.h********************/

#ifndef _CODE_H_
#define _CODE_H_

#include <string>
using namespace std;

class CCode
{
public:
string Encode(const string & str);
string Decode(const string & str);
};

#endif

/*****************code.cpp*************************/

#include "code.h"

string CCode::Encode(const string & str)
{
string ret="";
char buf[20];
int i=0;
while(i<str.length())
{
   if(str[i] & 0x80)
   {
    sprintf(buf,"%%%1X%1X",(unsigned char)str[i],(unsigned char)str[i+1]);
    ++i;
    ret+=buf;
   }
   else
    ret+=str[i];
   ++i;
}
return ret;
}

string CCode::Decode(const string & str)
{
string ret="";
string cur,all=str;
while(all.length()>0)
{
   int pos=all.find("%");
   if(pos!=0)
    ret+=all.substr(0,pos);
   cur=all.substr(pos+1,2);
   all=all.substr(pos+3);
   char ch;
   sscanf(cur.c_str(),"%x",&ch);
   ret+=(char)ch;
}
return ret;
}

/*************************http.h***************************/

#ifndef _HTTP_H_
#define _HTTP_H_

#include <winsock2.h>
#include <iostream>
#include <string>
using namespace std;

#pragma comment(lib,"ws2_32.lib")

#define BUFFER_SIZE 11400

class CHttp
{
public:
CHttp();
virtual ~CHttp();
private:
SOCKET m_SOCKET;
WSADATA m_WSADATA;
HOSTENT * m_HOSTENT;
SOCKADDR_IN m_SOCKADDR_IN;

char buf[BUFFER_SIZE];
int len;
private:
bool CreateSocket();
void ReleaseSocket();
public:
bool Connect(const string & httpAddr,const int port=80);
int SendData(const char * str);
string RecvData();
};

#endif

/************************http.cpp******************************/

#include "http.h"

void msg(char * str)
{
#ifdef _DEBUG
cout<<str<<endl;
#endif
}

CHttp::CHttp()
{
}

CHttp::~CHttp()
{
}

bool CHttp::CreateSocket()
{
if(WSAStartup(MAKEWORD(2,2),&m_WSADATA)==SOCKET_ERROR)
{
   msg("wsastartup");
   ReleaseSocket();
   return false;
}
if((m_SOCKET=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)
{
   msg("socket");
   ReleaseSocket();
   return false;
}
return true;
}

void CHttp::ReleaseSocket()
{
shutdown(m_SOCKET,SD_BOTH);
closesocket(m_SOCKET);
WSACleanup();
}

bool CHttp::Connect(const string & httpAddr,const int port)
{
if(! CreateSocket())
   return false;
if((m_HOSTENT=gethostbyname(httpAddr.c_str()))==NULL)
{
   msg("gethostbyname");
   ReleaseSocket();
   return false;
}
if(m_HOSTENT->h_addr_list[0]==NULL)
{
   msg("h_addr_list");
   ReleaseSocket();
   return false;
}
memset(&m_SOCKADDR_IN,0,sizeof(m_SOCKADDR_IN));
m_SOCKADDR_IN.sin_family=AF_INET;
m_SOCKADDR_IN.sin_port=htons(port);
m_SOCKADDR_IN.sin_addr.S_un.S_addr=*(ULONG *)m_HOSTENT->h_addr_list[0];

int timeOut=5000;
if(::setsockopt(m_SOCKET,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeOut,sizeof(timeOut))==SOCKET_ERROR)
   return false;
if(connect(m_SOCKET,(sockaddr *)&m_SOCKADDR_IN,sizeof(m_SOCKADDR_IN))==SOCKET_ERROR)
{
   msg("connect");
   ReleaseSocket();
   return false;
}
return true;
}

string CHttp::RecvData()
{
try
{
   len=recv(m_SOCKET,buf,sizeof(buf),0);
   if(len==SOCKET_ERROR)
    return "";
   buf[len]=0;
   return string(buf);
}
catch(...)
{
   return "";
}
}

int CHttp::SendData(const char * str)
{
return send(m_SOCKET,str,strlen(str),0);
}

/**************************main.cpp**************************/

#pragma warning (disable:4786)
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include "http.h"
#include "code.h"
using namespace std;

string StoreCookies(const string & strRecv) //从登陆接收的数据中分离出Cookie信息合并成发送的格式
{
string sCookies;
istringstream ssin(strRecv);
string line;
while(! getline(ssin,line).eof())
{
   if(line.find("cookie")!=string::npos)
   {
    int pos[2];
    if((pos[0]=line.find("\'",0))!=string::npos && (pos[1]=line.find("\'",pos[0]+1))!=string::npos)
    {
     if(sCookies.length()>0)
      sCookies+=";";
     sCookies+=line.substr(pos[0]+1,pos[1]-pos[0]-1);
    }
   }
}
return sCookies;
}

int main()
{
CHttp http;
http.Connect("bbs.jlu.edu.cn");

/******************登陆BBS并提取Cookie*********************/
string login="POST /cgi-bin/bbslogin HTTP/1.1\r\n";
login+="Content-Type: application/x-www-form-urlencoded\r\n";
login+="Host: bbs.jlu.edu.cn\r\n";
login+="Content-Length: 27\r\n\r\n"; //HTTP头结束,两个"\r\n"
login+="id=luosiyong&pw='yourpwd'\r\n\r\n"; //提交表单内容 这里pw经过了处理

http.SendData(login.c_str());
string sRecv=http.RecvData();

cout<<"login response >>>>>>\n"<<sRecv<<endl;
string sCookie=StoreCookies(sRecv); //从登陆的信息提取cookie用于后面验证

/*******************发帖*************************************/
string post="POST /cgi-bin/bbssnd?board=Arctic&u=0&r=0 HTTP/1.1\r\n";
post+="Content-Type: application/x-www-form-urlencoded\r\n";
post+="Host: bbs.jlu.edu.cn\r\n";
post+="Content-Length: 50\r\n";
post+="Cookie: \r\n\r\n";
post+="title=测试&signature=1&text=文本!@#$^*()_+|[]'内容\r\n"; //注意不能包含%和&符号,它们在HTTP中用于转义和变量连接

post.insert(post.find("Cookie: ")+strlen("Cookie: "),sCookie); //在http头中加入Cookie信息

http.SendData(post.c_str());
cout<<http.RecvData()<<endl;

/*******************注销登陆**********************************/
string logout="GET /cgi-bin/bbslogout HTTP/1.1\r\n";
logout+="Host: bbs.jlu.edu.cn\r\n";
logout+="Cookie: \r\n\r\n";

logout.insert(logout.find("Cookie: ")+strlen("Cookie: "),sCookie);

http.SendData(logout.c_str());
cout<<http.RecvData()<<endl;

return 0;
}

本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。

转载于:https://www.cnblogs.com/aquar/archive/2010/07/21/3451417.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Linux C编程中,要接收HTTP POST数据,首先需要建立一个用于监听网络连接的套接字,并绑定到指定的IP地址和端口号上。之后,通过该套接字接收客户端发来的HTTP请求。 接收HTTP POST数据的一种常用方法是通过读取套接字的输入缓冲区来获取数据。可以使用Linux C中的标准IO函数如read()或recv()来读取套接字中的数据。 接收HTTP POST数据的具体步骤如下: 1. 创建一个套接字: 使用socket()函数创建一个套接字,并指定为SOCK_STREAM类型。 2. 绑定IP地址和端口号: 使用bind()函数将套接字绑定到指定的IP地址和端口号上。 3. 监听网络连接: 使用listen()函数监听套接字,等待客户端的连接请求。 4. 接受客户端连接请求: 使用accept()函数接受客户端连接请求,并返回一个新的套接字,用于与客户端通信。 5. 读取HTTP POST数据: 使用read()或recv()函数从套接字中读取HTTP POST数据。根据HTTP协议规定,POST数据通常在HTTP请求头的之后。 6. 处理HTTP POST数据: 对于接收到的HTTP POST数据,可以根据具体需求进行处理、解析或存储。 7. 关闭套接字: 在完成数据处理后,使用close()函数关闭套接字,释放资源。 以上是Linux C接收HTTP POST数据的基本步骤。需要注意的是,在实际应用中还需要考虑网络异常和数据长度等问题,并做相应的错误处理和安全验证。 ### 回答2: 在Linux C中接收HTTP POST数据的过程可以分为以下几个步骤: 1. 创建一个Socket套接字:通过调用socket函数创建一个TCP套接字。 2. 绑定套接字到IP地址和端口:使用bind函数将套接字绑定到一个特定的IP地址和端口上。 3. 监听连接请求:通过调用listen函数,将套接字设置为监听模式,等待来自客户端的连接请求。 4. 接受客户端连接:使用accept函数接受客户端的连接请求,并返回一个新的套接字用于和客户端进行通信。 5. 接收HTTP请求数据:通过新的套接字读取客户端发送过来的数据。由于HTTP请求数据的传输采用TCP协议,可以使用recv函数接收数据。 6. 解析HTTP请求:解析从客户端接收到的HTTP请求数据,获取请求的方法、URL、请求头等信息。 7. 处理POST数据:当请求方法为POST时,从请求头中获取Content-Length字段的值,然后根据该值读取相应长度的数据。通过处理POST数据,可以获取客户端提交表单数据、文件等。 8. 返回HTTP响应:根据处理POST数据的结果,生成对应的HTTP响应数据,并通过新的套接字将响应数据发送给客户端。 9. 关闭套接字:通信完成后,使用close函数关闭套接字。 以上是大致的步骤,实际过程中还需要对各种错误和异常情况进行处理,例如连接失败、接收数据超时、请求方法不支持等。此外,需要熟悉HTTP协议和Socket编程的相关知识,才能更好地理解和实现上述步骤。这样,就能在Linux C中接收HTTP POST数据了。 ### 回答3: 在Linux下使用C语言接收HTTP POST数据,可以通过搭建一个简单的TCP服务器来实现。 首先,需要创建一个TCP socket,并绑定一个端口号,用于监听客户端的连接请求。然后,使用listen函数开始监听客户端连接。 接下来,使用accept函数接受客户端的连接请求,并使用recv函数从客户端接收数据。在接收数据之前,需要先解析HTTP头部,以获取POST数据的长度。 解析HTTP头部可以通过分析从recv函数接收到的数据来实现。通过查找HTTP头部的Content-Length字段,可以获取POST数据的长度。然后,使用recv函数循环接收指定长度的POST数据。 接收POST数据之后,可以对数据进行处理或解析,根据具体需求来决定如何处理接收到的数据。接收完毕后,可以发送回复给客户端,表示数据接收成功。 最后,使用close函数关闭与客户端的连接,并释放相关资源。 需要注意的是,上述方法是一个简单示例,能够实现基本的接收POST数据的功能,但在实际应用中可能需要更加复杂的处理逻辑,包括错误处理、并发处理等。此外,为了更高效地处理HTTP请求,可以考虑使用第三方库,如libcurl、libmicrohttpd等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值