Created
August 16, 2017 03:43
-
-
Save teraPacket/16006eb91ab3f8d3b3d5de33190acc7c to your computer and use it in GitHub Desktop.
example TCP client using libuv (version 1.0)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <uv.h> | |
//based on https://gist.githubusercontent.com/snatchev/5255976/ | |
//raw/8392c42d719bb775053036e32b21affdf932c1b7/libuv-tcp-client.c | |
//which was based on libuv 0.1, there is considerable difference there. | |
static void on_close(uv_handle_t* handle); | |
static void on_connect(uv_connect_t* req, int status); | |
static void on_write(uv_write_t* req, int status); | |
static uv_loop_t *loop; | |
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { | |
*buf = uv_buf_init(malloc(size), size); | |
} | |
void on_close(uv_handle_t* handle) | |
{ | |
printf("closed."); | |
} | |
void on_write(uv_write_t* req, int status) | |
{ | |
if (status) { | |
perror( "uv_write error "); | |
return; | |
} | |
printf("wrote.\n"); | |
free(req); | |
//uv_close((uv_handle_t*)req->handle, on_close); | |
} | |
void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) | |
{ | |
printf("on_read. %p\n",tcp); | |
if(nread >= 0) { | |
//printf("read: %s\n", tcp->data); | |
printf("read: %s\n", buf->base); | |
} | |
else { | |
//we got an EOF | |
uv_close((uv_handle_t*)tcp, on_close); | |
} | |
//cargo-culted | |
free(buf->base); | |
} | |
void write2(uv_stream_t* stream, char *data, int len2) { | |
uv_buf_t buffer[] = { | |
{.base = data, .len = len2} | |
}; | |
uv_write_t *req = malloc(sizeof(uv_write_t)); | |
uv_write(req, stream, buffer, 1, on_write); | |
} | |
void on_connect(uv_connect_t* connection, int status) | |
{ | |
if (status < 0) { | |
printf("failed to connect\n"); return; | |
} | |
printf("connected. %p %d\n",connection, status); | |
uv_stream_t* stream = connection->handle; | |
free(connection); | |
write2(stream, "echo world!", 12); | |
uv_read_start(stream, alloc_cb, on_read); | |
} | |
void startConn(char *host, int port) { | |
uv_tcp_t *pSock = malloc(sizeof(uv_tcp_t)); | |
uv_tcp_init(loop, pSock); | |
uv_tcp_keepalive(pSock, 1, 60); | |
struct sockaddr_in dest; | |
uv_ip4_addr(host, port, &dest); | |
uv_connect_t *pConn = malloc(sizeof(uv_connect_t)); | |
printf("allocated %p\n", pConn); | |
uv_tcp_connect(pConn, pSock, (const struct sockaddr*)&dest, on_connect); | |
} | |
int main(int argc, char **argv) { | |
loop = uv_default_loop(); | |
int i; | |
for (i=0; i<10; i++) | |
startConn("127.0.0.1", 80); | |
uv_run(loop, UV_RUN_DEFAULT); | |
} |
Hi @teraPacket and thanks for this example.
I did some additional test using valgrind
and I think in function on_close
you need to add
free(handle);
Check the output of valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all tcp_client
- Without
free(handle)
==3228== HEAP SUMMARY:
==3228== in use at exit: 2,736 bytes in 11 blocks
==3228== total heap usage: 43 allocs, 32 frees, 662,128 bytes allocated
==3228==
==3228== 256 bytes in 1 blocks are still reachable in loss record 1 of 3
==3228== at 0x4837D7B: realloc (vg_replace_malloc.c:826)
==3228== by 0x486DAE0: uv__io_start (in /usr/lib/x86_64-linux-gnu/libuv.so.1.0.0)
==3228== by 0x4877E18: uv__tcp_connect (in /usr/lib/x86_64-linux-gnu/libuv.so.1.0.0)
==3228== by 0x1094A3: startConn (libuv_tcp_client.c:79)
==3228== by 0x1094DB: main (libuv_tcp_client.c:86)
==3228==
==3228== 1,984 bytes in 8 blocks are indirectly lost in loss record 2 of 3
==3228== at 0x483577F: malloc (vg_replace_malloc.c:299)
==3228== by 0x10941D: startConn (libuv_tcp_client.c:70)
==3228== by 0x1094DB: main (libuv_tcp_client.c:86)
==3228==
==3228== 2,480 (496 direct, 1,984 indirect) bytes in 2 blocks are definitely lost in loss record 3 of 3
==3228== at 0x483577F: malloc (vg_replace_malloc.c:299)
==3228== by 0x10941D: startConn (libuv_tcp_client.c:70)
==3228== by 0x1094DB: main (libuv_tcp_client.c:86)
==3228==
==3228== LEAK SUMMARY:
==3228== definitely lost: 496 bytes in 2 blocks
==3228== indirectly lost: 1,984 bytes in 8 blocks
==3228== possibly lost: 0 bytes in 0 blocks
==3228== still reachable: 256 bytes in 1 blocks
==3228== suppressed: 0 bytes in 0 blocks
==3228==
==3228== For counts of detected and suppressed errors, rerun with: -v
==3228== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0
- With
free(handle)
==3236== HEAP SUMMARY:
==3236== in use at exit: 256 bytes in 1 blocks
==3236== total heap usage: 43 allocs, 42 frees, 662,128 bytes allocated
==3236==
==3236== 256 bytes in 1 blocks are still reachable in loss record 1 of 1
==3236== at 0x4837D7B: realloc (vg_replace_malloc.c:826)
==3236== by 0x486DAE0: uv__io_start (in /usr/lib/x86_64-linux-gnu/libuv.so.1.0.0)
==3236== by 0x4877E18: uv__tcp_connect (in /usr/lib/x86_64-linux-gnu/libuv.so.1.0.0)
==3236== by 0x1094AF: startConn (libuv_tcp_client.c:79)
==3236== by 0x1094E7: main (libuv_tcp_client.c:86)
==3236==
==3236== LEAK SUMMARY:
==3236== definitely lost: 0 bytes in 0 blocks
==3236== indirectly lost: 0 bytes in 0 blocks
==3236== possibly lost: 0 bytes in 0 blocks
==3236== still reachable: 256 bytes in 1 blocks
==3236== suppressed: 0 bytes in 0 blocks
==3236==
==3236== For counts of detected and suppressed errors, rerun with: -v
==3236== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
I hope it could be useful for anyone checking a good libuv 1.0 example
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
compile it as