Skip to content

Commit

Permalink
Add set_nodelay(), set_crok(), set_quickack() in svx_tcp_connection.
Browse files Browse the repository at this point in the history
Add more information about benchmark in README.md.
Version 0.0.10
  • Loading branch information
caikelun committed Feb 5, 2016
1 parent 1697c99 commit d27906b
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 30 deletions.
6 changes: 6 additions & 0 deletions CHANGES
@@ -1,3 +1,9 @@
2016-02-05 caikelun <caikelun@gmail.com>

* Add set_nodelay(), set_crok(), set_quickack() in svx_tcp_connection.
* Add more information about benchmark in README.md.
* Version 0.0.10

2016-02-02 caikelun <caikelun@gmail.com>

* Fix a bug about checking ports equality in svx_inetaddr.
Expand Down
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -92,6 +92,18 @@ libsvx/nginx and weighttp run in the same machine.

![libsvx vs. Nginx (2 threads/workers)](doc/bm_httpsvr_2.png)

**NOTICE:**

**The results of this benchmark test does not means libsvx have better performance than nginx.
Because of our test HTTP server is very simple, and does not achieve a complete HTTP protocol,
so we used very little CPU instruction for each HTTP requests.**

**libsvx does not do any special optimization for HTTP server usage scenario, libsvx is mainly
used to build custom protocol network programs in customized projects.**

**The purpose of this benchmark is to show that, libsvx have the ability to cope with
high-performance, concurrent network programs, and have no larger design flaws.**


Website, Clone and Download
---------------------------
Expand Down
37 changes: 25 additions & 12 deletions benchmarks/httpserver/main.c
Expand Up @@ -21,8 +21,18 @@
/* The HTTP server object */
static svx_tcp_server_t *server = NULL;

/* The callback to handle TCP connection established */
static void server_established_cb(svx_tcp_connection_t *conn, void *arg)
{
SVX_UTIL_UNUSED(arg);

/* In this simple program, although we always send all the response data in a single writing,
but we still set the TCP_NODELAY. To be more close to the real world HTTP server. */
if(svx_tcp_connection_set_nodelay(conn, 1)) exit(1);
}

/* The callback to handle HTTP request */
static void server_read(svx_tcp_connection_t *conn, svx_circlebuf_t *buf, void *arg)
static void server_read_cb(svx_tcp_connection_t *conn, svx_circlebuf_t *buf, void *arg)
{
SVX_UTIL_UNUSED(arg);

Expand All @@ -43,16 +53,16 @@ static void server_read(svx_tcp_connection_t *conn, svx_circlebuf_t *buf, void *
keep_alive = 0;

/* Build the HTTP response. */
char resp[1204];
size_t resp_len = snprintf(resp, sizeof(resp),
"HTTP/1.1 200 OK\r\n"
"Server: libsvx-simplest-HTTP-server\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 12\r\n"
"Connection: %s\r\n"
"\r\n"
"Hello world!",
keep_alive ? "keep-alive" : "close");
char resp[1024];
size_t resp_len = snprintf(resp, sizeof(resp),
"HTTP/1.1 200 OK\r\n"
"Server: libsvx-simplest-HTTP-server\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 12\r\n"
"Connection: %s\r\n"
"\r\n"
"Hello world!",
keep_alive ? "keep-alive" : "close");

/* Wirte the HTTP response to client. */
svx_tcp_connection_write(conn, (const uint8_t *)resp, resp_len);
Expand Down Expand Up @@ -82,8 +92,11 @@ static int server_start(svx_looper_t *looper, void *arg)
/* Set TCP keep-alive for discarding timeout connections. */
if(svx_tcp_server_set_keepalive(server, 5, 1, 3)) exit(1);

/* Set a callback fucntion for handling TCP connection established */
if(svx_tcp_server_set_established_cb(server, server_established_cb, NULL)) exit(1);

/* Set a callback function for handling HTTP request. */
if(svx_tcp_server_set_read_cb(server, server_read, NULL)) exit(1);
if(svx_tcp_server_set_read_cb(server, server_read_cb, NULL)) exit(1);

/* Start the HTTP server. */
if(svx_tcp_server_start(server)) exit(1);
Expand Down
2 changes: 1 addition & 1 deletion doc/Doxyfile
Expand Up @@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "libsvx"
PROJECT_NUMBER = 0.0.9
PROJECT_NUMBER = 0.0.10
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = doc
Expand Down
6 changes: 3 additions & 3 deletions src/svx_tcp_acceptor.c
Expand Up @@ -115,7 +115,7 @@ int svx_tcp_acceptor_destroy(svx_tcp_acceptor_t **self)
return 0;
}

int svx_tcp_acceptor_start(svx_tcp_acceptor_t *self, int if_reuse_port)
int svx_tcp_acceptor_start(svx_tcp_acceptor_t *self, int reuseport)
{
const int on = 1;
const int off = 0;
Expand All @@ -135,8 +135,8 @@ int svx_tcp_acceptor_start(svx_tcp_acceptor_t *self, int if_reuse_port)
SVX_LOG_ERRNO_GOTO_ERR(err, r = errno, NULL);

#ifdef SO_REUSEPORT
if_reuse_port = if_reuse_port ? 1 : 0;
if(0 != setsockopt(self->listen_fd, SOL_SOCKET, SO_REUSEPORT, &if_reuse_port, sizeof(if_reuse_port)))
reuseport = reuseport ? 1 : 0;
if(0 != setsockopt(self->listen_fd, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(reuseport)))
SVX_LOG_ERRNO_GOTO_ERR(err, r = errno, NULL);
#endif

Expand Down
8 changes: 4 additions & 4 deletions src/svx_tcp_acceptor.h
Expand Up @@ -77,13 +77,13 @@ extern int svx_tcp_acceptor_destroy(svx_tcp_acceptor_t **self);
/*!
* Start the TCP acceptor.
*
* \param[in] self The address of the TCP acceptor.
* \param[in] if_reuse_port Whether to enable SO_REUSEPORT for the listen fd.
* (SO_REUSEPORT was added from Linux kernel 3.9.0)
* \param[in] self The address of the TCP acceptor.
* \param[in] reuseport Whether to enable SO_REUSEPORT for the listen fd.
* (SO_REUSEPORT was added from Linux kernel 3.9.0)
*
* \return On success, return zero; on error, return an error number greater than zero.
*/
extern int svx_tcp_acceptor_start(svx_tcp_acceptor_t *self, int if_reuse_port);
extern int svx_tcp_acceptor_start(svx_tcp_acceptor_t *self, int reuseport);

/*!
* Stop the TCP acceptor.
Expand Down
34 changes: 34 additions & 0 deletions src/svx_tcp_connection.c
Expand Up @@ -9,6 +9,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/tcp.h>
#include "svx_tcp_connection.h"
#include "svx_inetaddr.h"
#include "svx_circlebuf.h"
Expand Down Expand Up @@ -706,3 +707,36 @@ int svx_tcp_connection_close(svx_tcp_connection_t *self)

return 0;
}

int svx_tcp_connection_set_nodelay(svx_tcp_connection_t *self, int on)
{
if(NULL == self) SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_INVAL, "self:%p\n", self);

on = (on ? 1 : 0);
if(0 != setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
SVX_LOG_ERRNO_RETURN_ERR(errno, NULL);

return 0;
}

int svx_tcp_connection_set_cork(svx_tcp_connection_t *self, int on)
{
if(NULL == self) SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_INVAL, "self:%p\n", self);

on = (on ? 1 : 0);
if(0 != setsockopt(self->fd, IPPROTO_TCP, TCP_CORK, &on, sizeof(on)))
SVX_LOG_ERRNO_RETURN_ERR(errno, NULL);

return 0;
}

int svx_tcp_connection_set_quickack(svx_tcp_connection_t *self, int on)
{
if(NULL == self) SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_INVAL, "self:%p\n", self);

on = (on ? 1 : 0);
if(0 != setsockopt(self->fd, IPPROTO_TCP, TCP_QUICKACK, &on, sizeof(on)))
SVX_LOG_ERRNO_RETURN_ERR(errno, NULL);

return 0;
}
33 changes: 33 additions & 0 deletions src/svx_tcp_connection.h
Expand Up @@ -351,6 +351,39 @@ extern int svx_tcp_connection_shutdown_wr(svx_tcp_connection_t *self);
*/
extern int svx_tcp_connection_close(svx_tcp_connection_t *self);

/*!
* Set TCP_NODELAY for the connection's fd.
*
* \param[in] self The address of the TCP connection.
* \param[in] on Whether to enable TCP_NODELAY for the connection's fd.
* \c 0 means off, \1 means on, default is off.
*
* \return On success, return zero; on error, return an error number greater than zero.
*/
extern int svx_tcp_connection_set_nodelay(svx_tcp_connection_t *self, int on);

/*!
* Set TCP_CORK for the connection's fd.
*
* \param[in] self The address of the TCP connection.
* \param[in] on Whether to enable TCP_CORK for the connection's fd.
* \c 0 means off, \1 means on, default is off.
*
* \return On success, return zero; on error, return an error number greater than zero.
*/
extern int svx_tcp_connection_set_cork(svx_tcp_connection_t *self, int on);

/*!
* Set TCP_QUICKACK for the connection's fd.
*
* \param[in] self The address of the TCP connection.
* \param[in] on Whether to enable TCP_QUICKACK for the connection's fd.
* \c 0 means off, \1 means on, default is off.
*
* \return On success, return zero; on error, return an error number greater than zero.
*/
extern int svx_tcp_connection_set_quickack(svx_tcp_connection_t *self, int on);

#ifdef __cplusplus
}
#endif
Expand Down
10 changes: 5 additions & 5 deletions src/svx_tcp_server.c
Expand Up @@ -67,7 +67,7 @@ struct svx_tcp_server
int keepalive_idle_s; /* <=0: do NOT send TCP keep-alive. >0: send period. */
int keepalive_intvl_s;
int keepalive_cnt;
int if_reuse_port;
int reuseport;
svx_tcp_connection_callbacks_t callbacks;
};

Expand Down Expand Up @@ -179,7 +179,7 @@ int svx_tcp_server_create(svx_tcp_server_t **self, svx_looper_t *looper, svx_ine
(*self)->keepalive_idle_s = 0;
(*self)->keepalive_intvl_s = 0;
(*self)->keepalive_cnt = 0;
(*self)->if_reuse_port = 0;
(*self)->reuseport = 0;
memset(&((*self)->callbacks), 0, sizeof((*self)->callbacks));

if(0 != (r = svx_tcp_server_add_listener(*self, listen_addr))) SVX_LOG_ERRNO_GOTO_ERR(err, r, NULL);
Expand Down Expand Up @@ -274,12 +274,12 @@ int svx_tcp_server_set_keepalive(svx_tcp_server_t *self, time_t idle_s, time_t i
return 0;
}

int svx_tcp_server_set_reuse_port(svx_tcp_server_t *self, int if_reuse_port)
int svx_tcp_server_set_reuseport(svx_tcp_server_t *self, int on)
{
if(NULL == self) SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_INVAL, "self:%p\n", self);

#ifdef SO_REUSEPORT
self->if_reuse_port = if_reuse_port ? 1 : 0;
self->reuseport = (on ? 1 : 0);
#else
SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_NOTSPT, "System does NOT support SO_REUSEPORT.\n");
#endif
Expand Down Expand Up @@ -407,7 +407,7 @@ int svx_tcp_server_start(svx_tcp_server_t *self)
}

TAILQ_FOREACH(listener, &(self->listeners), link)
if(0 != (r = svx_tcp_acceptor_start(listener->acceptor, self->if_reuse_port)))
if(0 != (r = svx_tcp_acceptor_start(listener->acceptor, self->reuseport)))
SVX_LOG_ERRNO_GOTO_ERR(err, r, NULL);

return 0;
Expand Down
8 changes: 4 additions & 4 deletions src/svx_tcp_server.h
Expand Up @@ -114,13 +114,13 @@ extern int svx_tcp_server_set_keepalive(svx_tcp_server_t *self,
/*!
* Set the SO_REUSEPORT for listen fd. (SO_REUSEPORT was added from Linux kernel 3.9.0)
*
* \param[in] self The address of the TCP server.
* \param[in] if_reuse_port Whether to enable SO_REUSEPORT for the listen fd.
* \param[in] self The address of the TCP server.
* \param[in] on Whether to enable SO_REUSEPORT for the listen fd.
* \c 0 means off, \1 means on, default is off.
*
* \return On success, return zero; on error, return an error number greater than zero.
*/
extern int svx_tcp_server_set_reuse_port(svx_tcp_server_t *self,
int if_reuse_port);
extern int svx_tcp_server_set_reuseport(svx_tcp_server_t *self, int on);

/*!
* Set the read buffer length for all TCP connections.
Expand Down
2 changes: 1 addition & 1 deletion src/svx_version.c
Expand Up @@ -9,7 +9,7 @@

#define SVX_VERSION_MAJOR 0
#define SVX_VERSION_MINOR 0
#define SVX_VERSION_EXTRA 9
#define SVX_VERSION_EXTRA 10

#define SVX_VERSION ((SVX_VERSION_MAJOR << 16) | (SVX_VERSION_MINOR << 8) | (SVX_VERSION_EXTRA))

Expand Down

0 comments on commit d27906b

Please sign in to comment.