这个可以用libevent实现http客户端的post get等功能

http_client.h

#ifndef __HTTP_CLIENT_H__
#define __HTTP_CLIENT_H__#include <sys/queue.h>enum http_method
{HTTP_METHOD_GET,HTTP_METHOD_POST,HTTP_METHOD_HEAD,HTTP_METHOD_PUT,HTTP_METHOD_DELETE,
};struct http_client;struct http_header
{size_t      key_len;const char *key;size_t      value_len;const char *value;TAILQ_ENTRY(http_header) entry;
};struct http_response
{struct http_request *request;uint16_t          status;size_t            url_len;const char       *url;size_t            body_len;const char       *body;bool              body_chunked;TAILQ_HEAD(,http_header) headers;
};struct http_request;/* Callback functions */
typedef void (*cb_http_response)(struct http_client *, struct http_request *, struct http_response *, void *baton);
typedef void (*cb_http_disconnect)(struct http_client *, void *baton);/** * New http_client connection instance * * @param hostname  Hostname or ip address of web server.* @param port * @param ssl * * @return struct http_client* Client connection handle.*/
struct http_client *http_client_new(const char *hostname, const char *port, SSL_CTX* ssl_ctx);/*** Close http_client connection, cancel all pending requests.* * @param api */
void http_client_free(struct http_client *api);/*** Queue a new HTTP client request.* * @param api * @param method * @param uri_len * @param uri * * @return struct http_request* */
struct http_request *http_client_request(struct http_client *api, enum http_method method, size_t uri_len,const char *uri);int http_client_request_add_header(struct http_request *request, const char *key, const char *value);int http_client_request_add_body(struct http_request *request, size_t body_len, const char *body);/*** Make this request pending.* * @param request * @return int success / failure flag.*/
int http_client_request_dispatch(struct http_request *request, cb_http_response callback, void *baton);/* TODO: */
int http_client_cancel(struct http_request *request);#endif /* __HTTP_CLIENT_H__ */

http_client.c

/* libc */
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
/* libevent */
#include <event2/event-config.h>
#include <event2/event.h>
/* openssl */
#include <openssl/bio.h>
#include <openssl/ssl.h>
/* http_client */
#include "http_client.h"#define VERSION_MAJOR 0
#define VERSION_MINOR 1#define FLAGS_HAVE_USER_AGENT       0x0001
#define FLAGS_HAVE_CONTENT_LENGTH   0x0002
#define FLAGS_HAVE_HOST             0x0004
#define FLAGS_HAVE_KEEP_ALIVE       0x0008enum connection_fault {FAULT_OKAY, FAULT_CLOSE, FAULT_ERROR, FAULT_FREE,
};enum parse_state {PARSE_ERROR = -1, PARSE_MORE_DATA = 0, PARSE_NEXT_STATE = 1,
};enum http_state {HTTP_NOT_CONNECTED,HTTP_CONNECTING,HTTP_IDLE,HTTP_READING_STATUS_LINE,HTTP_READING_HEADERS,HTTP_READING_BODY,HTTP_READING_DONE,HTTP_SENDING,
};struct http_request {struct http_client *api;struct evbuffer *output;enum http_method method;size_t uri_len;const char *uri;TAILQ_HEAD(,http_header)headers;size_t body_len;const char *body;/* User per request baton. */cb_http_response callback;void *baton;TAILQ_ENTRY(http_request) entry;
};struct http_client {
uint16_t version[2];
const char* host;struct {const char *hostname;const char *port;SSL_CTX* ssl_ctx;SSL* ssl;BIO* buffer_io;struct event ev;
} connection;enum http_state state;cb_http_disconnect cb_disconnect;TAILQ_HEAD(, http_request)
pending_request;struct http_response *current;
struct evbuffer *input;void *baton;
};/*======================================================================================================================* *  Function prototypes* *====================================================================================================================== */static void libevent_interopt(int fd, short what, void *baton);
static int read_data(struct http_client *api);
static int write_request(struct http_client *api);
static void connection_fault(struct http_client *api,enum connection_fault fault);
static int next_request(struct http_client *api);
static BIO* connect_remote_host(struct http_client *api);/*======================================================================================================================* *  Util functions.* *====================================================================================================================== */static
void *memdup(const void *src, size_t len) {
void *output;if ((output = malloc(len)) == NULL) {return NULL;
}return memcpy(output, src, len);
}static
void reschedule_event(struct event *ev, int fd, short what, void *baton) {
event_del(ev);
event_set(ev, fd, what, libevent_interopt, baton);
event_add(ev, NULL);
}static
const char *get_method_str(enum http_method method) {
switch (method) {
case HTTP_METHOD_GET:return "GET";
case HTTP_METHOD_POST:return "POST";
default:return NULL;
}
}static struct http_header* find_header(struct http_response *response,const char *name) {
struct http_header *cur;TAILQ_FOREACH(cur, &response->headers, entry)
{if (strncmp(cur->key, name, cur->key_len) == 0)return cur;
}return NULL;
}/*======================================================================================================================* *  Request / response creation destruction.* *====================================================================================================================== */static struct http_header* new_header(const char *key, size_t key_len,const char *value, size_t value_len) {
struct http_header* header = calloc(1, sizeof(*header));if (header == NULL) {goto FAIL;
}header->key_len = key_len;
header->value_len = value_len;if ((header->key = strndup(key, key_len)) == NULL) {goto FAIL_TWO;
}if ((header->value = strndup(value, value_len)) == NULL) {goto FAIL_TWO;
}return header;FAIL_TWO: free((void *) header->key);
free((void *) header->value);
FAIL: free(header);
return NULL;
}static struct http_response* new_response(struct http_request *request) {
struct http_response *response = calloc(1, sizeof(*response));if (response == NULL) {return NULL;
}response->request = request;
TAILQ_INIT(&response->headers);return response;FAIL: free(response);
return NULL;
}static
void free_response(struct http_response *response) {
while (!TAILQ_EMPTY(&response->headers)) {struct http_header *cur = TAILQ_FIRST(&response->headers);TAILQ_REMOVE(&response->headers, cur, entry);free(cur);
}free(response);
}static struct http_request* new_request(struct http_client *api) {
struct http_request *request;if ((request = calloc(1, sizeof(*request))) == NULL)goto FAIL_ONE;if ((request->output = evbuffer_new()) == NULL)goto FAIL_TWO;TAILQ_INIT(&request->headers);
request->api = api;return request;FAIL_TWO: free(request);
FAIL_ONE: return NULL;
}static
void free_request(struct http_request *request) {
while (!TAILQ_EMPTY(&request->headers)) {struct http_header *cur = TAILQ_FIRST(&request->headers);TAILQ_REMOVE(&request->headers, cur, entry);free(cur);
}free((void *) request->uri);
free((void *) request->body);evbuffer_free(request->output);
free(request);
}/*======================================================================================================================* *  Parse response* *====================================================================================================================== */static bool is_connection_close(struct http_client *api,struct http_response *response) {
struct http_header *header = find_header(response, "Connection");if (header == NULL) {goto SKIP;
}if (api->version[VERSION_MINOR] == 1) {if (header && strncasecmp(header->value, "Close", header->value_len))return false;
} else if (api->version[VERSION_MINOR] == 0) {if (strncasecmp(header->value, "Keep-Alive", header->value_len) == 0)return true;
}SKIP: return (api->version[VERSION_MINOR] == 1);
}static ssize_t get_body_len(struct http_response *response) {
struct http_header *header = find_header(response, "Content-Length");if (header)return atoi(header->value);return -1;
}static bool is_response_chunked(struct http_client *api,struct http_response *response) {
return false;
}int find_body_len(struct http_client *api, struct http_response *response) {
if (is_response_chunked(api, response)) {response->body_chunked = true;return 0;
}ssize_t body_len = get_body_len(response);if (body_len < 0) {return -1;
}response->body_len = body_len;return 0;
}static enum parse_state read_status_line(struct http_client *api,struct http_response *response) {
enum parse_state status;
char *line = evbuffer_readln(api->input, NULL, EVBUFFER_EOL_CRLF_STRICT);
char *token = line;/* Need more data. */
if (line == NULL) {return PARSE_MORE_DATA;
}char *protocol = strsep(&token, " ");
char *status_code = strsep(&token, " ");if (protocol == NULL || status_code == NULL) {status = PARSE_ERROR;goto DONE;
}if (strcmp(protocol, "HTTP/1.0") == 0) {api->version[VERSION_MINOR] = 0;
} else if (strcmp(protocol, "HTTP/1.1") == 0) {api->version[VERSION_MINOR] = 1;
} else {/* Unknow protocol version. */status = PARSE_ERROR;
}response->status = atoi(status_code);status = PARSE_NEXT_STATE;DONE: free(line);
return status;
}static enum parse_state read_header_line(struct http_client *api,struct http_response *response) {
char *line, *sep, *value;do {line = evbuffer_readln(api->input, NULL, EVBUFFER_EOL_CRLF_STRICT);if (line == NULL) {/* Need more data. */free(line);return PARSE_MORE_DATA;} else if (*line == '\t' || *line == ' ') {/* Header contination. *//* TODO: */} else if (*line == '\0') {/* Header / body boundry. */free(line);/* Figure out the body we should be looking for. */if (find_body_len(api, response) == -1)return PARSE_ERROR;return PARSE_NEXT_STATE;}if ((sep = index(line, ':')) == NULL)return PARSE_ERROR;for (value = sep + 1; value != '\0'; value++) {if (*value == ' ' || *value == '\t') {continue;} else {break;}}struct http_header* header = new_header(line, sep - line, value,strlen(value));if (header == NULL) {return PARSE_ERROR;}TAILQ_INSERT_TAIL(&response->headers, header, entry);free(line);
} while (1);
}static enum parse_state read_body(struct http_client *api,struct http_response *response) {
/* Special case that cannot have a body:*   - 1xx status*   - 204 status*   - 304 status*   - HEAD method*/
if ((response->status >= 100 && response->status <= 199)|| response->status == 204 || response->status == 304|| response->request->method == HTTP_METHOD_HEAD) {return PARSE_NEXT_STATE;
}/* Chunked encomding. */
if (0)return PARSE_MORE_DATA;return (EVBUFFER_LENGTH(api->input) >= response->body_len) ?PARSE_NEXT_STATE : PARSE_MORE_DATA;
}static
int dispatch_response(struct http_client *api, struct http_response *response) {
struct http_request *request = TAILQ_FIRST(&api->pending_request);TAILQ_REMOVE(&api->pending_request, request, entry);/* Tempoary pointer into the evbuffer. */
response->body = EVBUFFER_DATA(api->input);if (request->callback != NULL) {request->callback(api, request, response, request->baton);
}/* Get rid of the body from the buffer. */
evbuffer_drain(api->input, response->body_len);if (response->body_chunked == true) {/* Chunked, already closed connection */
} else if (is_connection_close(api, response)) {if (response != NULL) {connection_fault(api, FAULT_CLOSE);}
} else {api->state = HTTP_IDLE;
}/* Free response & request. */
free_response(response);
free_request(request);api->current = NULL;return 0;
}static
int read_response(struct http_client *api) {
enum parse_state result;do {switch (api->state) {case HTTP_READING_STATUS_LINE:result = read_status_line(api, api->current);break;case HTTP_READING_HEADERS:result = read_header_line(api, api->current);break;case HTTP_READING_BODY:result = read_body(api, api->current);break;case HTTP_READING_DONE:if ((result = dispatch_response(api, api->current)) == 0) {next_request(api);return 0;}}switch (result) {/* Need more data. */case PARSE_MORE_DATA:break;/* Increment FSM to next state. */case PARSE_NEXT_STATE:api->state++;break;/* Error. */case PARSE_ERROR:default:connection_fault(api, FAULT_ERROR);return -1;}
} while (result == 1);
}/*======================================================================================================================* *  Create request buffer* *====================================================================================================================== */static
int add_req_line(struct http_request *request) {
const char *method_str = get_method_str(request->method);return evbuffer_add_printf(request->output, "%s %.*s HTTP/%i.%i\r\n",method_str, request->uri_len, request->uri,request->api->version[VERSION_MAJOR],request->api->version[VERSION_MINOR]);
}static
int add_header(struct evbuffer *buffer, struct http_header *header) {
return evbuffer_add_printf(buffer, "%.*s: %.*s\r\n", header->key_len,header->key_len, header->value_len, header->value);
}static
int add_headers(struct http_request *request) {
int flags = 0;/* Add other headers */
struct http_header *cur;
TAILQ_FOREACH(cur, &request->headers, entry)
{if (strncmp(cur->key, "Host", cur->key_len) == 0)flags |= FLAGS_HAVE_HOST;else if (strncmp(cur->key, "Content-Length", cur->key_len) == 0)flags |= FLAGS_HAVE_CONTENT_LENGTH;else if (strncmp(cur->key, "User-Agent", cur->key_len) == 0)flags |= FLAGS_HAVE_USER_AGENT;else if (strncmp(cur->key, "Connection", cur->key_len) == 0)flags |= FLAGS_HAVE_KEEP_ALIVE;add_header(request->output, cur);
}if (!(flags & FLAGS_HAVE_HOST)) {evbuffer_add_printf(request->output, "Host: %s\r\n",request->api->connection.hostname);
}if (!(flags & FLAGS_HAVE_CONTENT_LENGTH) && request->body_len > 0) {evbuffer_add_printf(request->output, "Conntent-Length: %i\r\n",request->body_len);
}if (!(flags & FLAGS_HAVE_USER_AGENT)) {evbuffer_add_printf(request->output, "User-Agent: Admeld http_client\r\n");
}if (!(flags & FLAGS_HAVE_KEEP_ALIVE)) {evbuffer_add_printf(request->output, "Connection: Keep-Alive\r\n");
}return 0;
}static
int add_body(struct http_request *request) {
if (request->body_len > 0) {evbuffer_add(request->output, request->body, request->body_len);
}return 0;
}static
int next_request(struct http_client *api) {
if (TAILQ_EMPTY(&api->pending_request)) {event_del(&api->connection.ev);api->state = HTTP_IDLE;return 0;
}/* Schedule write. */
if (event_pending(&api->connection.ev, EV_READ | EV_WRITE, NULL)) {reschedule_event(&api->connection.ev, api->connection.ev.ev_fd, EV_WRITE,api);
} else {int fd;BIO_get_fd(api->connection.buffer_io, &fd);event_set(&api->connection.ev, fd, EV_WRITE, libevent_interopt, api);event_add(&api->connection.ev, NULL);
}api->state = HTTP_SENDING;return 0;
}/*======================================================================================================================* *  Connection write, read, parse state machine.* *====================================================================================================================== */static
void connection_fault(struct http_client *api, enum connection_fault fault) {
/* Fault all pending request. */
if (fault != FAULT_CLOSE) {struct http_request *request;for (request = TAILQ_FIRST(&api->pending_request); request != NULL;request = TAILQ_FIRST(&api->pending_request)) {/* Run callback, with an error response. */if (request->callback != NULL)request->callback(api, request, NULL, request->baton);TAILQ_REMOVE(&api->pending_request, request, entry);free_request(request);}
}if (fault == FAULT_CLOSE && api->current) {if (api->current->body_chunked == true) {/* Set the length, it's the whole buffer. */api->current->body_len = EVBUFFER_LENGTH(api->input);dispatch_response(api, api->current);}/* TODO: Error, cancel pending request / response. */
}/* Run disconnect callback. */
if (api->cb_disconnect != NULL)api->cb_disconnect(api, api->baton);/* TODO: close connection. *//* Set status FSM. */
api->state = HTTP_NOT_CONNECTED;/* Reset BIO but try to keep resume SSL session on reconnect. */
if (api->connection.ssl_ctx) {BIO_reset(api->connection.buffer_io);
}/* Process remaning requests. */
if (fault == FAULT_CLOSE && !TAILQ_EMPTY(&api->pending_request)) {if ((api->connection.buffer_io = connect_remote_host(api)) == NULL) {/* Error, dump the queue. */connection_fault(api, FAULT_ERROR);}
}
}static
int ssl_negociate(struct http_client *api) {
/* Do handshake. *//* Verify ceficate. */
if (SSL_get_verify_result(api->connection.ssl) != X509_V_OK)return -1;/* Wait till we can write out request out. */
reschedule_event(&api->connection.ev, api->connection.ev.ev_fd, EV_WRITE, api);return 0;
}static
void libevent_interopt(int fd, short what, void *baton) {
int result;
struct http_client *api = (struct http_client *) baton;switch (api->state) {
case HTTP_CONNECTING:if (api->connection.ssl_ctx) {if (ssl_negociate(api) == -1) {}return;} else {api->state = HTTP_SENDING;/* And fall through. */}
case HTTP_SENDING:/* Write the data out. */write_request(api);return;
case HTTP_READING_STATUS_LINE:
case HTTP_READING_HEADERS:
case HTTP_READING_BODY:do {/* Read into evbuffer */if ((result = read_data(api)) == -1)return;} while (result == 1);/* Do the read callback. */read_response(api);return;
case HTTP_IDLE:/*  */;
}
}/*======================================================================================================================* *  Network IO* *====================================================================================================================== */static
int write_request(struct http_client *api) {
struct http_request *request;if (TAILQ_EMPTY(&api->pending_request)) {return 0;
}request = TAILQ_FIRST(&api->pending_request);int result = BIO_write(api->connection.buffer_io,EVBUFFER_DATA(request->output), EVBUFFER_LENGTH(request->output));if (result < 1) {if (BIO_should_retry(api->connection.buffer_io)) {return 0;}connection_fault(api, FAULT_ERROR);return -1;
}/* Drain the data we wrote out. */
evbuffer_drain(request->output, result);if (EVBUFFER_LENGTH(request->output) == 0) {if ((api->current = new_response(request)) == NULL)return -1;api->state = HTTP_READING_STATUS_LINE;/* Turn off write notification and turn on read notification. */reschedule_event(&api->connection.ev, api->connection.ev.ev_fd, EV_READ,api);
}return 0;
}static
int read_data(struct http_client *api) {
char buffer[1024];int result = BIO_read(api->connection.buffer_io, buffer, sizeof(buffer));if (result > 0) {evbuffer_add(api->input, buffer, result);return (result >= sizeof(buffer));
} else if (result == 0) {/* Other side closed the connection */connection_fault(api, FAULT_CLOSE);return -1;
}/* We'll try again in the future again. */
if (BIO_should_retry(api->connection.buffer_io)) {return 0;
}/* Error */
connection_fault(api, FAULT_ERROR);
return -1;
}static BIO* connect_remote_host(struct http_client *api) {
BIO *result;if (api->connection.ssl_ctx != NULL) {result = BIO_new_ssl_connect(api->connection.ssl_ctx);if (result) {BIO_set_conn_hostname(result, api->connection.hostname);BIO_get_ssl(result, &api->connection.ssl);SSL_set_mode(api->connection.ssl, SSL_MODE_AUTO_RETRY);}} else {result = BIO_new_connect((char *) api->connection.hostname);
}if (result == NULL) {goto FAIL_ONE;
}BIO_set_conn_port(result, api->connection.port);/* Set it to non-blocking mode. */
BIO_set_nbio(result, 1);if (BIO_do_connect(result) == -1) {if (BIO_should_retry(result)) {int reason = BIO_get_retry_reason(result);} else {goto FAIL_TWO;}
}int fd;
BIO_get_fd(result, &fd);
short what = (api->connection.ssl_ctx) ? EV_READ : EV_WRITE;event_set(&api->connection.ev, fd, what, libevent_interopt, api);
event_add(&api->connection.ev, NULL);api->state = HTTP_CONNECTING;return result;FAIL_TWO: BIO_free_all(result);
FAIL_ONE: return NULL;
}static
int setup_ssl(struct http_client *api, SSL_CTX* ctx) {
api->connection.ssl_ctx = ctx;
api->connection.ssl = NULL;
}/*======================================================================================================================* *  Public API * *====================================================================================================================== */struct http_client *http_client_new(const char *hostname, const char *port,SSL_CTX* ssl_ctx) {
struct http_client *api = calloc(1, sizeof(*api));if (api == NULL) {goto FAIL_ONE;
}api->version[VERSION_MAJOR] = 1;
api->version[VERSION_MINOR] = 1;api->state = HTTP_NOT_CONNECTED;TAILQ_INIT(&api->pending_request);if ((api->connection.hostname = strdup(hostname)) == NULL)goto FAIL_TWO;
if ((api->connection.port = strdup(port)) == NULL)goto FAIL_TWO;if (ssl_ctx != NULL) {if (setup_ssl(api, ssl_ctx) == -1)goto FAIL_TWO;
}if ((api->input = evbuffer_new()) == NULL) {goto FAIL_THREE;
}return api;FAIL_THREE: evbuffer_free(api->input);
FAIL_TWO: free((void *) api->connection.hostname);
free((void *) api->connection.port);
free(api);
FAIL_ONE: return NULL;
}void http_client_free(struct http_client *api) {
BIO_free_all(api->connection.buffer_io);connection_fault(api, FAULT_FREE);free(api);
}struct http_request *http_client_request(struct http_client *api,enum http_method method, size_t uri_len, const char *uri) {
struct http_request *request = new_request(api);if (request == NULL)return NULL;request->method = method;
request->uri_len = uri_len;if ((request->uri = memdup(uri, uri_len)) == NULL) {goto FAIL;
}return request;FAIL: free_request(request);
return NULL;
}int http_client_request_add_header(struct http_request *request,const char *key, const char *value) {
struct http_header *header = malloc(sizeof(*header));if (header == NULL) {goto FAIL_ONE;
}header->key_len = strlen(key);
header->value_len = strlen(value);if ((header->key = memdup(key, header->key_len)) == NULL) {goto FAIL_TWO;
}if ((header->value = memdup(value, header->value_len)) == NULL) {goto FAIL_THREE;
}TAILQ_INSERT_TAIL(&request->headers, header, entry);
return 0;FAIL_THREE: free((void *) header->key);
FAIL_TWO: free(header);
FAIL_ONE: return -1;
}int http_client_request_add_body(struct http_request *request, size_t body_len,const char *body) {
if ((request->body = malloc(body_len)) == NULL) {return -1;
}memcpy((void *) request->body, body, body_len);
request->body_len = body_len;return 0;
}int http_client_request_dispatch(struct http_request *request,cb_http_response callback, void *baton) {
struct http_client *api = request->api;
BIO *bio;request->callback = callback;
request->baton = baton;if (add_req_line(request) == -1) {return -1;
}if (add_headers(request) == -1) {return -1;
}if (add_body(request) == -1) {return -1;
}if (evbuffer_add_printf(request->output, "\r\n") == -1)return -1;/* Stick in the stack for sending it out. */
TAILQ_INSERT_TAIL(&request->api->pending_request, request, entry);switch (request->api->state) {
case HTTP_NOT_CONNECTED:if ((bio = connect_remote_host(request->api)) == NULL) {return -1;}api->connection.buffer_io = bio;return 0;
case HTTP_IDLE:/* Schedule processing of the next request. */next_request(api);
}return 0;
}

test.c

/* libc */
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
/* libevent */
#include <event2/event-config.h>
#include <event2/event.h>
/* openssl */
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>#include "http_client.h"void callback(struct http_client *api, struct http_request *req, struct http_response *response, void *baton)
{printf("%.*s", response->body_len, response->body);
}int main(int argc, char *argv[])
{bool          do_ssl = false;const char   *url = argv[1];const char   *domain = argv[1];const char   *port = argv[2];const char   *uri = argv[3];if (argc < 4) {printf("ERROR: Need url, port and uri\n");return 1;}SSL_load_error_strings();ERR_load_BIO_strings();OpenSSL_add_all_algorithms();event_init();struct http_client   *client = http_client_new(domain, port, NULL);struct http_request  *req = http_client_request(client, HTTP_METHOD_GET, strlen(uri), uri);http_client_request_dispatch(req, callback, NULL);event_loop(0);return 1;
}

基于libevent的http客户端,并可以请求https相关推荐

  1. mysql查询过程从客户端发送查询请求_MySQL查询过程和高级查询

    最近有个需求,要修改现有存储结构,涉及查询条件和查询效率的考量,看了几篇索引和HBase相关的文章,回忆了相关知识,结合项目需求,说说自己的理解和总结. 总体目录如下,上篇介绍了前3小节,分析了索引为 ...

  2. 基于Libevent的HTTP Server

    简单的Http Server 使用Libevent内置的http相关接口,可以很容易的构建一个Http Server,一个简单的Http Server如下: #include <event2/e ...

  3. TCP/IP网络编程_第6章基于UDP的服务器端/客户端

    6.1 理解 DUP 我们在第4章学习TCP的过程中, 还同时了解了 TCP/IP 协议. 在4层TCP/IP模型中, 上数第二层传输(Transport)层分为TCP和UDP这两种. 数据交换过程可 ...

  4. 基于TCP的服务器端/客户端的C语言代码实现和工作原理

    网络协议系列1介绍了:基于网络协议的套接字一般分为TCP套接字和UDP套接字,TCP套接字是面向对象(steam) 数据通信中协议栈分为7层,对于程序员而言,掌握4层协议栈就足够了. 下面将重点介绍这 ...

  5. 四 基于TCP的服务器端/客户端

    ** 第四章 基于TCP的服务器端/客户端(1) ** 主要内容: 这里我们讨论通过套接字收发数据 1.TCP与UDP的区别数据传输方式不同 2.协议栈的层次关系:链路层->IP层->tc ...

  6. OPC通讯开发简介——基于WTOPCSVR的OPC服务器端和基于WTCLIENT的OPC客户端开发

    OPC通讯开发简介--基于WTOPCSVR的OPC服务器端和基于WTCLIENT的OPC客户端开发 说明 一.OPC技术背景及介绍 二.OPC通讯的流程(OPC经典架构) 三.OPC标准官方文件部分变 ...

  7. python 基于多路复用的多客户端管理

    九.基于多路复用的多客户端管理 作者:解琛 时间:2020 年 9 月 7 日 九.基于多路复用的多客户端管理 9.1 select 9.2 用 select 实现处理多个 socket 客户端请求 ...

  8. http协议跟服务器交互,基于HTTP协议的客户端与服务器之间的数据交互方法专利_专利查询 - 天眼查...

    L-种基于HTTP协议的客户端与服务器之间的数据交互方法,应用于智能$居系统 中,以使用户的客户端与智能家居系统的服务器之间建立稳定的网络连接并进行数据交 互,所述方法包括步骤: 所述客户端与所述服务 ...

  9. 基于Android微博整合客户端的设计与实现 毕业设计论文开题报告

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! < ...

最新文章

  1. 路过的朋友们,最后一天投票,感谢
  2. docker配置国内镜像源
  3. [Android工具]更新音乐下载软件,MP3音乐无损音乐下载器
  4. C++map的基本操作和使用
  5. ucla研究生计算机科学,详解UCLA研究生录取数据,达到什么标准才能稳被录?
  6. UML学习——类图(三)
  7. 微前端与项目实施方案研究
  8. android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘
  9. QT @ VS2017的安装
  10. startx启动过程分析
  11. 人生规划:20岁到60岁我该干什么
  12. 计算机网络学习笔记(5. 电路交换)
  13. access mysql 操作方法_操作ACCESS数据库注意事项
  14. 面试题:100个白球,100个黑球,每次取两个
  15. 《Java和Android开发实战详解》
  16. 什么是驻点和拐点_拐点和驻点的区别有哪些
  17. 机器学习:朴素贝叶斯算法对新闻分类
  18. 郑州大学计算机课程表查询,郑州大学研究生课程表
  19. mac安装正在计算机,出现“无法在计算机上安装macOS”错误时该怎么办?
  20. Promise 是什么?

热门文章

  1. SAP ABAP 系列丛书推荐:PP 报工
  2. 神舟笔记本WLAN打不开的解决方法
  3. 华为交换机配置基础命令
  4. 贴片电阻的封装和功率关系
  5. 12306的“短信公众号”到底是个啥?
  6. 三菱fx5u modbus tcp fb块用法_FX5U强势来袭
  7. 同城服务小程序开发的好处和功能方案介绍
  8. Oracle获取指定月最后一天日期(last_day函数)
  9. Java:三大特性之继承性
  10. 视频提取关键帧的三种方式【已调通】