练习使用 socket 发送简单的 HTTP GET 请求
最近项目中有这样的需求,需要在游戏中内嵌手机验证模块,而手机绑定信息保存在运营后台,游戏服务器无法直接访问,所以就需要游戏服务器向运营后台发送一些 HTTP 请求来获取这类的信息。因为这部分功能写在服务端,为了尽量避免服务器阻塞,在 recv 前加了 select 操作,并且为每个 HTTP 请求分配了一个线程。这里是针对此需求做的一些练习。
[cpp]
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
// 连接服务器发送消息并将接收数据保存到 pReceiveBuf 中,此过程会 select 并 recv 消息,直到没有数据到达或者接收缓存已满
int connectAndSendData(const char *szHost, unsigned short nPort, const char *pDataToSend, unsigned int nDataSize, char *pReceiveBuf = NULL, unsigned int *pnReceiveSize = NULL)
{
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
int err = ::WSAStartup(wVersionRequested, &wsaData);
if ( 0 != err )
{
printf("[connectAndSendData]: WSAStartup failed. return %d. \r\n", err);
return -1;
}
if ( wsaData.wVersion != wVersionRequested )
{
printf("[connectAndSendData]: wsaData.wVersion %d is not equal to wVersionRequested %d.\r\n", wsaData.wVersion, wVersionRequested);
::WSACleanup();
return -2;
}
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( INVALID_SOCKET == sock )
{
printf("[connectAndSendData]: socket error %d. \r\n", WSAGetLastError());
return -3;
}
struct hostent *p_hostent = gethostbyname(szHost);
if( NULL == p_hostent )
{
printf("[gethostbyname]: socket error %d. \r\n", WSAGetLastError());
::closesocket(sock);
::WSACleanup();
return -4;
}
SOCKADDR_IN addr_server;
addr_server.sin_family = AF_INET;
addr_server.sin_addr = *((struct in_addr*)p_hostent->h_addr);
memset(addr_server.sin_zero, 0, 8);
addr_server.sin_port = htons(nPort);
err = ::connect(sock, (SOCKADDR*)&addr_server, sizeof(addr_server));
if ( SOCKET_ERROR == err )
{
printf("[connectAndSendData]: connect %s:%d error %d. \r\n", szHost, nPort, WSAGetLastError());
::closesocket(sock);
::WSACleanup();
return -5;
}
err = ::send(sock, pDataToSend, nDataSize, 0);
if ( SOCKET_ERROR == err )
{
printf("[connectAndSendData]: send error %d. \r\n", WSAGetLastError());
}
if ( NULL != pReceiveBuf && NULL != pnReceiveSize )
{
char *p_receive = pReceiveBuf;
char *p_buf = p_receive;
int n_buf_len = *pnReceiveSize;
int n_len = n_buf_len - 1;
int n_read = 0;
char temp[256];
int n_head_len = -1;
int n_content_len = -1;
const char *content = NULL;
while (1)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
struct timeval timeo;
timeo.tv_sec = 10;
timeo.tv_usec = 1000;
int ret = select(sock, &fds, NULL, NULL, &timeo);
if (ret <= 0)
break;
if (FD_ISSET(sock, &fds))
{
n_read = ::recv(sock, p_buf, n_len, 0);
if (n_read <= 0)
break;
p_buf += n_read;
n_len -= n_read;
if ( n_len == 0 )
break;
const char *rnrn = strstr(p_receive, "\r\n\r\n");
if (NULL != rnrn && rnrn < p_buf)
{
rnrn += 4;
content = rnrn;
if (-1 == n_content_len)
{
const char *content_length = strstr(p_receive, "Content-Length: ");
if (NULL != content_length && content_length < p_buf)
&
补充:软件开发 , C++ ,
上一个:poj - 2318 - TOYS
下一个:修改窗体客户区区域
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊