我用http协议上传 图片 但是 收到的 响应 有问题 求大神帮助
调用方法
stringstrRecv;
intnRetUpload = 0;
CSDKUploadPic MySend;
//strRecv.substr(
//设置上传服务器的地址
MySend.SetServerInfo("192.168.1.110","/Default.aspx");
//如果要提交其他的数据,请使用下面的格式,第一个参数为表单名,第二个为表单值
//MySend.MakePostData("homepage","www.lilu.name");
nRetUpload = MySend.UploadPic("2.jpg","img",strRecv);
#include <string>
#include <Windows.h>
using namespace std;
//提交图片函数,返回值说明
//目前仅支持ASCII编码,不支持UTF8,和unicode。
//定义错误信息
#define UPLOAD_SUCCESS200
#define UPLOAD_WSASTARTUP_ERROR 101
#define UPLOAD_SOCKET_ERROR102
#define UPLOAD_CONNECT_ERROR103
#define UPLOAD_SEND_ERROR104
#define UPLOAD_FILEOPEN_ERROR105
#define UPLOAD_RECV_ERROR106
class CSDKUploadPic
{
public:
DWORD GetHostAddr(const char* lpHost);
void SetServerInfo(char *pHost,char *pRelativeUrl,WORD nPort = 80);
CSDKUploadPic();
~CSDKUploadPic();
//99:图片不存在
//200:正常成功
//101:服务器无法连接
//102:提交页面无法打开
//103:数据发送失败
//404:访问链接未找到
//405:服务器无法支持该请求方式
//500:异常错误
int UploadPic(char *pPicPath,char *pPostName,string &strRecv);
int MakePostData(char *pPostName,char *pPostValue);
protected:
private:
stringm_strPostData;//要发送的数据内容
charm_szPostEndData[200];//协议尾部数据
intm_nContentLen;//数据包字节数
WORDm_nPort;//端口
charm_szRelativeURL[200];//相对URL地址,如:/test/upload.asp
charm_szHost[100];//主机。如:www.lilu.name,或者192.168.0.1
charm_szBoundary[50];//协议内容分隔符,这个不用管。
char*m_pDataBuff;//数据缓存指针,图片,接收数据
const intm_nBuffSize;//缓存的大小
int MakeHeaderData(char *szBuff);
int MakePostPicData(char *pPostName,char *pPicPath);
int MakeEndData();
bool ValidHostChar(char ch);//地址是否合法
};
#include <winsock.h>
#include "SDKUploadPic.h"
#pragma comment(lib,"ws2_32")
CSDKUploadPic::CSDKUploadPic():m_nContentLen(0),m_nBuffSize(65536)
{
strcpy(m_szBoundary,"-----------2893749wrjhewf");
m_pDataBuff = NULL;
}
CSDKUploadPic::~CSDKUploadPic()
{
if (m_pDataBuff)
{
delete []m_pDataBuff;
m_pDataBuff = NULL;
}
}
int CSDKUploadPic::UploadPic(char *pPicPath,char *pPostName,
string &strRecv)
{
intnRetCode = UPLOAD_SUCCESS;
WSADATAwsadata = {0};
SOCKETsockServer = 0;
SOCKADDR_INaddrServer = {0};//服务器地址
intnRetSend = 0;//发生数据返回值
intnRetRecv = 0;//接收数据返回值
FILE*pFile = NULL;//图片句柄
intnPicSize = 0;//图片大小
intnChunkCount = 0;//图片被分成几块传送
intnLeftLen = 0;//还剩下的字节数
inti = 0;//循环索引
//intnRetLen = 0;//每次发送的字节数
intnIndex = 0;//发送字节的位置索引
if ( 0 != WSAStartup(MAKEWORD(2,2),&wsadata))
{
nRetCode = UPLOAD_WSASTARTUP_ERROR;
goto EXIT0;
}
sockServer = socket(AF_INET,SOCK_STREAM,0);
if (sockServer == INVALID_SOCKET)
{
nRetCode = UPLOAD_SOCKET_ERROR;
goto EXIT0;
}
//服务器信息
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(m_nPort);
addrServer.sin_addr.S_un.S_addr = GetHostAddr(m_szHost);
//连接
if (SOCKET_ERROR == connect(sockServer,(const sockaddr*)&addrServer,sizeof(addrServer)))
{
nRetCode = UPLOAD_CONNECT_ERROR;
goto EXIT0;
}
//开辟缓存
if (m_pDataBuff == NULL)
{
m_pDataBuff = new char[m_nBuffSize];
memset(m_pDataBuff,0,m_nBuffSize);
}
else
{
memset(m_pDataBuff,0,m_nBuffSize);
}
//////////////////////////////////////////////////////////////////////////
//首先发送数据头与图片之前的数据
MakeEndData();
nPicSize = MakePostPicData(pPostName,pPicPath);//生成图片前缀数据,同时加上图片大小。
MakeHeaderData(m_pDataBuff);
m_strPostData = m_pDataBuff + m_strPostData;
nRetSend = send(sockServer,m_strPostData.c_str(),m_strPostData.size(),0);
if (nRetSend <= 0)
{
nRetCode = UPLOAD_SEND_ERROR;
goto EXIT0;
}
//发送图片数据
pFile = fopen(pPicPath,"rb");
if (pFile == NULL )
{
//wprintf(L"打开文件错误!\n");
return UPLOAD_FILEOPEN_ERROR;
}
fseek(pFile,0,SEEK_SET);
//计算块数
nChunkCount = nPicSize / m_nBuffSize + 1;
for (i = 1; i <= nChunkCount; i++)
{
//最后一块
if (i == nChunkCount)
{
nLeftLen = nPicSize - m_nBuffSize * (i-1);
}
else
{
nLeftLen = m_nBuffSize;
}
//定位文件并读取到缓存中。
fread(m_pDataBuff,nLeftLen,1,pFile);
//循环发送直到发送完毕。
nIndex = 0;
while(nLeftLen > 0)
{
nRetSend = send(sockServer,&m_pDataBuff[nIndex],nLeftLen,0);
if (nRetSend == SOCKET_ERROR)
{
break;
}
nLeftLen -= nRetSend;
nIndex += nRetSend;
}
printf("正在发送第%d块数据!\n",i);
}
//关闭文件,释放资源
fclose(pFile);
printf("图片发送完毕!\n");
pFile = NULL;
//发送尾部构造数据
nRetSend = send(sockServer,m_szPostEndData,strlen(m_szPostEndData),0);
if (nRetSend <= 0)
{
nRetCode = UPLOAD_SEND_ERROR;
goto EXIT0;
}
//////////////////////////////////////////////////////////////////////////
//接收数据
//nRetRecv = recv(sockServer,m_pDataBuff,m_nBuffSize,0);
//if (nRetRecv == SOCKET_ERROR)
//{
//nRetCode = UPLOAD_RECV_ERROR;
//goto EXIT0;
//}
//while(nRetRecv > 0)
//{
//strRecv += m_pDataBuff;
////如果缓存接收满了,表示后面还有数据。——这样判断是不准确的,先这样暂时处理。
//nRetRecv = recv(sockServer,m_pDataBuff,m_nBuffSize,0);
//if (nRetRecv == m_nBuffSize)
//{
//nRetRecv = recv(sockServer,m_pDataBuff,m_nBuffSize,0);
//}
//else
//{
//break;
//}
//}
while(true)
{
nRetRecv = recv(sockServer,m_pDataBuff,m_nBuffSize,0);
if(nRetRecv == 0)
{
break;
}
else if(nRetRecv == SOCKET_ERROR)
{
nRetCode = UPLOAD_RECV_ERROR;
goto EXIT0;
}
else
{
strRecv += m_pDataBuff;
}
}
EXIT0:
if (m_pDataBuff)
{
delete []m_pDataBuff;
m_pDataBuff = NULL;
}
if (sockServer != INVALID_SOCKET)
{
closesocket(sockServer);
WSACleanup();
}
return nRetCode;
}
int CSDKUploadPic::MakeHeaderData(char *szBuff)
{
return sprintf(szBuff,"POST %s HTTP/1.1\r\n"
"Accept: text/html,*/*\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Accept-Language: zh-cn\r\n"
"Content-Type: multipart/form-data; boundary=%s\r\n"
"Cache-Control: no-cache\r\n"
"Connection:Close\r\n"
"Cache-Control: no-cache\r\n"
"Content-length:%d\r\n"
"Host: %s:%d\r\n\r\n",
m_szRelativeURL,m_szBoundary,m_nContentLen,m_szHost,m_nPort
);
}
int CSDKUploadPic::MakePostData(char *pPostName,char *pPostValue)
{
charszBuff[1024] = {0};
int nRet = sprintf(szBuff,"--%s\r\nContent-Disposition: form-data; name="%s"\r\n\r\n%s\r\n",
m_szBoundary,pPostName,pPostValue);
m_nContentLen += nRet;
m_strPostData += szBuff;
return nRet;
}
int CSDKUploadPic::MakePostPicData(char *pPostName,char *pPicPath)
{
charszBuff[1024] = {0};
FILE*pFile = NULL;
int nRet = sprintf(szBuff,"--%s\r\nContent-Disposition: form-data; name="%s";filename="%s"\r\nContent-Type: image/pjpeg\r\n\r\n",
m_szBoundary,pPostName,pPicPath);
m_nContentLen += nRet;
m_strPostData += szBuff;
//获取文件大小
pFile = fopen(pPicPath,"rb");
if (pFile == NULL )
{
//wprintf(L"打开文件错误!\n");
return -1;
}
fseek(pFile,0,SEEK_END);
nRet = ftell(pFile);
rewind(pFile);
fclose(pFile);
m_nContentLen += nRet;
return nRet;
}
int CSDKUploadPic::MakeEndData()
{
int nRet = sprintf(m_szPostEndData,"\r\n--%s\r\nContent-Disposition: form-data; name="Submit"\r\n\r\nsubmit\r\n--%s--",
m_szBoundary,m_szBoundary);
m_nContentLen += nRet;
return nRet;
}
//设置服务器信息
void CSDKUploadPic::SetServerInfo(char *pHost, char *pRelativeUrl, WORD nPort)
{
strcpy(m_szHost,pHost);
strcpy(m_szRelativeURL,pRelativeUrl);
m_nPort = nPort;
}
DWORD CSDKUploadPic::GetHostAddr(const char* lpHost)
{
hostent *phost = NULL;
char*p = NULL;
intiAddrLen = 0;
inti = 0;
//判断,如果是IP地址
iAddrLen = strlen(lpHost);
for (i = 0; i < iAddrLen; i++)
{
//如果即不是数字,也不是点
if ((!isdigit(lpHost[i])) && (lpHost[i] != '.'))
{
break ;
}
//如果检测完毕
if (i == iAddrLen - 1)
{
return inet_addr(lpHost);
}
}
//如果不是IP地址,是网址,检测地址是否合法
for (i = 0; i < iAddrLen; i++)
{
if (!ValidHostChar(lpHost[i]))
{
return 0 ;
}
}
phost = gethostbyname(lpHost);
if (phost == NULL)
{
return 0;
}
//获取地址列表指针
p = *(phost->h_addr_list);
//可以使用下面的代码将IP地址打印出来
//printf("address:%d.%d.%d.%d\n",p[0][0] & 0x00ff,p[0][1] & 0x00ff,p[0][2] & 0x00ff,p[0][3] & 0x00ff);
//printf("address:%02x.%02x.%02x.%02x\n",p[0][0] & 0x00ff,p[0][1] & 0x00ff,p[0][2] & 0x00ff,p[0][3] & 0x00ff);
return *((unsigned long*)p);
}
bool CSDKUploadPic::ValidHostChar(char ch)
{
return (isalpha(ch) || isdigit(ch) || ch == '-' || ch == '.' || ch == ':'|| ch == '/');
}
//这是我之前写的,先收头,这样接收的!然后解析头中信息
//根据头中len再去接收消息体
int RecHttpHead(int socketFd, char *pBuffer, unsigned int Time)
{
char RecBuf[2] = {'\0'};
int ret = 0;
char s8Flag = 0;
int RecvLen = 0;
while(1)
{
// ret = ReadData(socketFd, RecBuf, 1, Time);
if((ret = recv(socketFd, RecBuf, 1, 0)) <= 0)
{
printf( "[%s]-[%d]: revc error:%s\n", __func__, __LINE__, strerror(errno));
printf( "[%s]-[%d]: revc error:%d\n", __func__, __LINE__, ret);
return -1;
}
if (ret < 0 )
{
printf("[%s]-[%d] :Read head failed\n", __FILE__, __LINE__ );
return -1;
}
switch(*RecBuf)
{
case '\r':
s8Flag++;
break;
case '\n':
s8Flag++;
break;
default:
s8Flag = 0;
break;
}
strcat(pBuffer, RecBuf);
RecvLen += ret;
if( s8Flag >= 4)
break;
}
return RecvLen;
}
返回告诉你了,gzip压缩的,先解压
int deflateUncompress(const char *src, uint32 length, string &buffer)
{
buffer.clear();
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
int ret = inflateInit2(&strm, 47);//-MAX_WBITS);
if (ret != Z_OK)
return ret;
strm.avail_in = length;
strm.next_in = (unsigned char*)src;
static size_t CHUNK = 1024;
char *out = new char[CHUNK];
do
{
strm.avail_out = CHUNK;
strm.next_out = (Bytef*)out;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR)
{
delete[] out;
//throw p2p_cmd_exception_protocol_err( "deflateUncompress Z_STREAM_ERROR!" );
return ret;
}
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
delete[] out;
return ret;
}
buffer.append(out, CHUNK - strm.avail_out);
} while (strm.avail_out == 0);
inflateEnd(&strm);
delete[] out;
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
content-length 31就不对,还是服务器问题
额...我服务器就这两句话..