⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c_http.c

📁 C编写的用来实现search engine的推荐功能
💻 C
📖 第 1 页 / 共 2 页
字号:
		switch (ret) {
		case SOCKET_ERROR:
		case SOCKET_CLOSED:
			return readByte;
		case SOCKET_TIMEOUT:
			break;
		default:
#ifdef PROCESS_EXTRA
			if (pHeaders->processExtraResponse != NULL) {
				if (!(*(pHeaders->processExtraResponse))(
					pHeaders->extraResp,
					ret,
					&(pHeaders->respProcessed),
					response,
					size
				   ))
				{
					return readByte;
				}
			}
#endif
			break;
		}
	}
	
	return readByte;
}

/* 发送HTTP请求,内部函数,输入参数line的初始内容为请求行 */
static int sendHTTPRequest(int hSocket, char* line, const char* inHeaders, URLINFO* urlInfo, int timeout)
{
	int err = SOCKET_ERROR;
	
	if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
	{
		goto EXIT;
	}
	sprintf(line, "Host: %s", urlInfo->host);
	if (urlInfo->port != DEFAULT_PORT)
	{
		sprintf(line + strlen(line), ":%d", urlInfo->port);
	}
	if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
	{
		goto EXIT;
	}
	if (SendLine(hSocket, CONTENT_TYPE, timeout) == SOCKET_ERROR)
	{
		goto EXIT;
	}
	if (SendLine(hSocket, USER_AGENT, timeout) == SOCKET_ERROR)
	{
		goto EXIT;
	}
	if (urlInfo->user != NULL)
	{
		char auth[512];
		int len;
		
		len = sprintf(line, "%s:%s", urlInfo->user, urlInfo->passwd==NULL?"":urlInfo->passwd);
		len = Base64Encode(line, len, auth, 511, 0);
		auth[len] = '\0';
		sprintf(line, "%s %s", BASIC_AUTH, auth);
		if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
		{
			goto EXIT;
		}
	}
	/* 输出额外的头信息 */
	if (inHeaders != NULL)
	{
		if (SendLine(hSocket, inHeaders, timeout) == SOCKET_ERROR)
		{
			goto EXIT;
		}
	}
	err = 0;
	
EXIT:
	return err;
}

/**
 * 以HEAD方式做HTTP请求
 * IN:
 *  url:        HTTP的URL,可以带query_string('?'后面的部分),例:http://user:passwd@host:port/file?query
 *  inHeaders:  请求头信息,如设置cookie的头信息,可以传NULL,格式是:"Header1: value1\nHeader2: value2",最后一个不加'\n'
 *  outHeaders: 响应的头信息,见HTTP_RESPONSE_HEADER_T定义,必须不为NULL
 *  timeout:    访问超时秒数,传0使用缺省值
 * OUT:
 *  0: 发生错误,错误原因可看headers中的errMsg
 *  >0: 请求成功,这时headers中的errMsg为NULL,其余信息见headers中其它字段
 */
int HTTPRequestHead(const char* url, const char* inHeaders, HTTP_RESPONSE_HEADER_T* outHeaders, int timeout)
{
	int errno = NO_ERROR;
	URLINFO urlInfo = {0};
	char line[1024];
	int len = 0;
	
	int hSocket = INVALID_SOCKET;
	
	if (outHeaders == NULL || !validHTTPParams(url, outHeaders, "", 1, &urlInfo))
	{
		return 0;
	}
	timeout = getResponseTimeOut(timeout);
	hSocket = NonbSocket(urlInfo.host, urlInfo.port, timeout);
	if (hSocket == INVALID_SOCKET)
	{
		errno = CONNECTION_ERROR;
		goto EXIT;
	}
	
	/* send HTTP Request */
	sprintf(line, "HEAD %s HTTP/1.0", urlInfo.file);
	if (sendHTTPRequest(hSocket, line, inHeaders, &urlInfo, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	if (SendLine(hSocket, BLANK_LINE, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	
	/* read response */
	len = readResponse(hSocket, outHeaders, line, NULL, 0, &errno, timeout);

EXIT:
	freeURLInfo(&urlInfo);
	if (hSocket != INVALID_SOCKET)
	{
		CloseSocket(hSocket);
	}
	if (outHeaders != NULL)
	{
		outHeaders->errMsg = ERROR_MESSAGE[errno];
	}
	return len;
}

/**
 * 以GET方式做HTTP请求
 * IN:
 *  url:        HTTP的URL,可以带query_string('?'后面的部分),例:http://user:passwd@host:port/file?query
 *  inHeaders:  请求头信息,如设置cookie的头信息,可以传NULL,格式是:"Header1: value1\nHeader2: value2",最后一个不加'\n'
 *  outHeaders: 响应的头信息,见HTTP_RESPONSE_HEADER_T定义,可以传NULL
 *  timeout:    访问超时秒数,传0使用缺省值
 *  response:   存放响应结果的内存区
 *  size:       response的空间大小
 * OUT:
 *  0: 发生错误,错误原因可看headers中的errMsg
 *  >0: response中的有效字符数,这时headers中的errMsg为NULL
 * 【注意】:response中不会添加字符串结束标志'\0',因为结果也可以是二进制内容
 */
int HTTPRequestGet(const char* url, const char* inHeaders, HTTP_RESPONSE_HEADER_T* outHeaders, int timeout, char* response, int size)
{
	int errno = NO_ERROR;
	URLINFO urlInfo = {0};
	char line[1024];
	int len = 0;
	
	int hSocket = INVALID_SOCKET;
	
	if (!validHTTPParams(url, outHeaders, response, size, &urlInfo))
	{
		return 0;
	}
	timeout = getResponseTimeOut(timeout);
	hSocket = NonbSocket(urlInfo.host, urlInfo.port, timeout);
	if (hSocket == INVALID_SOCKET)
	{
		errno = CONNECTION_ERROR;
		goto EXIT;
	}
	
	/* send HTTP Request */
	sprintf(line, "GET %s HTTP/1.0", urlInfo.file);
	if (sendHTTPRequest(hSocket, line, inHeaders, &urlInfo, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	if (SendLine(hSocket, BLANK_LINE, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	
	/* read response */
	len = readResponse(hSocket, outHeaders, line, response, size, &errno, timeout);

EXIT:
	freeURLInfo(&urlInfo);
	if (hSocket != INVALID_SOCKET)
	{
		CloseSocket(hSocket);
	}
	if (outHeaders != NULL)
	{
		outHeaders->errMsg = ERROR_MESSAGE[errno];
	}
	return len;
}

/**
 * 以POST方式做HTTP请求
 * IN:
 *  url:        HTTP的URL,可以带query_string('?'后面的部分),例:http://user:passwd@host:port/file?query
 *  postBody:   需要通过POST方式传送的数据,如果为NULL,会传送url中的query_string部分
 *  bodyLen:    postBody的长度,因为postBody可以是二进制内容,如果postBody为NULL时可传任意值
 *  inHeaders:  请求头信息,如设置cookie的头信息,可以传NULL,格式是:"Header1: value1\nHeader2: value2",最后一个不加'\n'
 *  outHeaders: 响应的头信息,见HTTP_RESPONSE_HEADER_T定义,可以传NULL
 *  timeout:    访问超时秒数,传0使用缺省值
 *  response:   存放响应结果的内存区
 *  size:       response的空间大小
 * OUT:
 *  0: 发生错误,错误原因可看headers中的errMsg
 *  >0: response中的有效字符数,这时headers中的errMsg为NULL
 * 【注意】:response中不会添加字符串结束标志'\0',因为结果也可以是二进制内容
 */
int HTTPRequestPost(const char* url, const char* postBody, int bodyLen, const char* inHeaders, HTTP_RESPONSE_HEADER_T* outHeaders, int timeout, char* response, int size)
{
	int errno = NO_ERROR;
	URLINFO urlInfo = {0};
	char line[1024];
	int len = 0;
	const char* body;
	
	int hSocket = INVALID_SOCKET;
	
	if (!validHTTPParams(url, outHeaders, response, size, &urlInfo))
	{
		return 0;
	}
	
	/* 取body/bodyLen */
	if (postBody != NULL)
	{
		body = postBody;
	}
	else
	{
		body = urlInfo.query;
		if (body != NULL)
		{
			*((char*)(body-1)) = '\0'; /* URL中的'?'设为0 */
			bodyLen = strlen(body);
		}
		else
		{
			bodyLen = 0;
		}
	}
	
	timeout = getResponseTimeOut(timeout);
	hSocket = NonbSocket(urlInfo.host, urlInfo.port, timeout);
	if (hSocket == INVALID_SOCKET)
	{
		errno = CONNECTION_ERROR;
		goto EXIT;
	}
	
	/* send HTTP Request */
	sprintf(line, "POST %s HTTP/1.0", urlInfo.file);
	if (sendHTTPRequest(hSocket, line, inHeaders, &urlInfo, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	sprintf(line, "Content-Length: %d", bodyLen);
	if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	if (SendLine(hSocket, BLANK_LINE, timeout) == SOCKET_ERROR)
	{
		errno = COMM_ERROR;
		goto EXIT;
	}
	
	//send request body
	if (bodyLen > 0)
	{
		if (Send(hSocket, (const char*)body, bodyLen, timeout) == SOCKET_ERROR)
		{
			errno = COMM_ERROR;
			goto EXIT;
		}
	}
	
	/* read response */
	len = readResponse(hSocket, outHeaders, line, response, size, &errno, timeout);

EXIT:
	freeURLInfo(&urlInfo);
	if (hSocket != INVALID_SOCKET)
	{
		CloseSocket(hSocket);
	}
	if (outHeaders != NULL)
	{
		outHeaders->errMsg = ERROR_MESSAGE[errno];
	}
	return len;
}

/* 测试用 */
void dumpResponseHeaders(HTTP_RESPONSE_HEADER_T* headers, FILE* out)
{
	if (headers == NULL || out == NULL)
	{
		return;
	}
	
	fprintf(out, "Error: %s\n"
				 "statusCode: %s\n"
				 "Content-Type: %s\n"
				 "Content-Length: %d\n"
				 "Date: %s\n"
				 "Server: %s\n"
				 "Last-Modified: %s\n"
				 "Location: %s\n",
				 (headers->errMsg?headers->errMsg:NO_HEADER),
				 (headers->statusCode[0]?headers->statusCode:NO_HEADER),
				 (headers->contentType[0]?headers->contentType:NO_HEADER),
				 headers->contentLength,
				 (headers->date[0]?headers->date:NO_HEADER),
				 (headers->server[0]?headers->server:NO_HEADER),
				 (headers->lastModified[0]?headers->lastModified:NO_HEADER),
				 (headers->location[0]?headers->location:NO_HEADER)
			);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -