libevent http client 구현
5932 단어 libeventasiohttp-parser
제 결승전 글 인'Qt Quick 이미지 처리 인 스 턴 스 의 미 투 쇼(원본 다운로드)'에 투표 해 주 십시오.감사합니다.
libevent 를 기반 으로 한 client 엔 드 의 예 를 찾 고 싶 었 지만 적당 한 것 을 찾 지 못 하고 스스로 만 들 었 습 니 다.질문 이 있 으 면 http 요청 을 하면 상대방 은 항상 반응 이 없습니다.오늘 evhttp 소스 코드 를 연구 하 다가 갑자기 어 리 석 은 오류 가 발견 되 었 습 니 다.요청 을 보 낼 때 빈 줄 이 하나 빠 졌 습 니 다("\r").아,재주 가 대단 하군.
사실은 libevent 의 이벤트 처리 체 제 를 이용 하여 Liux 와 안 드 로 이 드 두 시스템 에서 일부 기능 모듈 을 공유 하려 면 먼저 httpclient 를 가지 고 시험 을 해 보 려 고 합 니 다.http 사용parser 에서 httpheader 를 해석 해 주 셔 서 감사합니다.
순수 C 의 환경 에서 시험 한 것 으로 나 는 두 개의 보조 구조 체(함수 포인터 모방 류 의 실현)를 실현 했다.struct c_string 문자열 처리 에 사용,struct tagvalue_list 는 http header field 와 header value 를 저장 하 는 데 사 용 됩 니 다.나의 실험 은 libevent 를 잘 알 고 있 는데,이 코드 들 이 스 쳐 지나 갔다.
main.c 의 코드 를 살 펴 보 겠 습 니 다.주로 libevent 를 어떻게 사용 하 는 지 알 아 보 겠 습 니 다.
#include "event2/event-config.h"
#include "event2/event_compat.h"
#include "event2/event.h"
#include "event2/util.h"
#include "event2/bufferevent.h"
#include "event2/dns.h"
#include "event2/buffer.h"
#include "http_client.h"
#ifndef WIN32
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <string.h>
void write_cb(evutil_socket_t sock, short flags, void * args)
{
struct http_client *httpc = (struct http_client *)args;
struct c_string * string = httpc->request_string(httpc);
int len = string->len(string);
int sent = 0;
int ret = 0;
printf("connected, write headers: %s
", string->data);
ret = send(sock, string->data, len, 0);
while(ret != -1)
{
sent += ret;
if(sent == len) break;
ret = send(sock, string->data + sent, len - sent, 0);
}
delete_c_string(string);
event_add((struct event*)httpc->user_data[1], 0);
}
void read_cb(evutil_socket_t sock, short flags, void * args)
{
struct http_client *httpc = (struct http_client*)args;
int ret = recv(sock, httpc->parse_buffer, PARSE_BUFFER_SIZE, 0);
printf("read_cb, read %d bytes
", ret);
if(ret > 0)
{
httpc->process_data(httpc, httpc->parse_buffer, ret);
}
else if(ret == 0)
{
printf("read_cb connection closed
");
event_base_loopexit((struct event_base*)httpc->user_data[0], NULL);
return;
}
if(httpc->finished(httpc) != 0)
{
event_add((struct event*)httpc->user_data[1], 0);
}
}
static evutil_socket_t make_tcp_socket()
{
int on = 1;
evutil_socket_t sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
evutil_make_socket_nonblocking(sock);
#ifdef WIN32
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on, sizeof(on));
#else
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
#endif
return sock;
}
static struct http_client * make_http_client(struct event_base * base, const char *url)
{
struct http_client * httpc = new_http_client();
/* initialize http client */
httpc->user_data[0] = base;
if(0 == httpc->parse_url(httpc, url) )
{
httpc->add_request_header(httpc, "Accept", "*/*");
httpc->add_request_header(httpc, "User-Agent", "test http client");
return httpc;
}
delete_http_client(httpc);
printf("parse url failed
");
return 0;
}
int download(struct event_base * base, const char *url)
{
evutil_socket_t sock = make_tcp_socket();
struct sockaddr_in serverAddr;
struct http_client * httpc = make_http_client(base, url);
struct event * ev_write = 0;
struct event * ev_read = 0;
struct timeval tv={10, 0};
if(!httpc) return -1;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(httpc->port);
#ifdef WIN32
serverAddr.sin_addr.S_un.S_addr = inet_addr(httpc->host);
#else
serverAddr.sin_addr.s_addr = inet_addr(httpc->host);
#endif
memset(serverAddr.sin_zero, 0x00, 8);
connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
ev_write = event_new(base, sock, EV_WRITE, write_cb, (void*)httpc);
ev_read = event_new(base, sock, EV_READ , read_cb, (void*)httpc);
httpc->user_data[1] = ev_read;
event_add(ev_write, &tv);
return 0;
}
int main(int argc, char** argv)
{
struct event_base * base = 0;
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
if(argc < 2)
{
printf("usage: %s http://111.222.333.44:8080/xxx.htm
now only support ip.
", argv[0]);
return 1;
}
base = event_base_new();
if( 0 == download(base, argv[1]) )
{
event_base_dispatch(base);
event_base_free(base);
}
else
{
printf("prepare download failed for %s
", argv[1]);
}
return 0;
}
예 는 간단 합 니 다.명령 행 을 통 해 지정 한 URL 대표 자원 을 다운로드 하고 다운로드 한 자원 도 처리 되 지 않 았 습 니 다.(추 후 struct http 에 게 전달 할 수 있 습 니 다.client 데이터 처리 인 터 페 이 스 를 추가 하여 데 이 터 를 처리 합 니 다).현재 windows 와 cent os 에서 실행 할 수 있 습 니 다.
프로그램 이 엄밀 하지 않 고 일부 오류 가 처리 되 지 않 았 으 며 일부 메모리 가 풀 리 지 않 았 습 니 다.libevent 를 사용 하여 client 프로그램 을 실현 하 는 방법 만 보 여 줍 니 다.대략 다음 절 차 를 거치 면 된다.
저 는 bufferevent 를 사용 하지 않 았 습 니 다.인터넷 에 많은 예 가 있 습 니 다.더 이상 언급 하지 않 겠 습 니 다.다음은 성공 할 수 있 는 지 UDP 를 시험 해 보고 싶 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
libevent의 사용 방법 - 서버의 간단한 실례다음은 각 함수와 작업에 대해 설명합니다. 1,main (): 주 함수는 연결을 감청하는 플러그인을 만들고 accept () 의 리셋 함수를 만들어서 이벤트 처리 함수를 통해 모든 연결을 처리합니다. 2、accept...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.