Skip to content

Instantly share code, notes, and snippets.

@chinaestone
Forked from Jxck/README.md
Last active August 29, 2015 14:14
Show Gist options
  • Save chinaestone/cc0707c462f96f058416 to your computer and use it in GitHub Desktop.
Save chinaestone/cc0707c462f96f058416 to your computer and use it in GitHub Desktop.

first, we should thanks Jxck write this libuv example . but there's some mistake in the example . In order to let the newbies learn libuv better and easy , I fixed these bugs . this example is based on libuv version 0.1.xx . and I use libuv version 0.1.19 to fixed these bugs .

the main mistake is the callback result , all the error code where lower than zero . not only -1. so I fixed these bugs . and I translate the commit to english .

how to compile

$ gcc -g -Wall -I /path/to/libuv/include /path/to/libuv/uv.a -framework CoreServices server.c -o server
$ gcc -g -Wall -I /path/to/libuv/include /path/to/libuv/uv.a -framework CoreServices client.c -o client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#define log(x) printf("%s\n", x);
uv_loop_t *loop; // the event pool , all of the tcp event will be fire by this instance
void on_connect(uv_connect_t *req, int status);
void on_write_end(uv_write_t *req, int status);
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t suggested_size);
void echo_read(uv_stream_t *server, ssize_t nread, uv_buf_t buf);
// print the server response
void echo_read(uv_stream_t *server, ssize_t nread, uv_buf_t buf) {
if (nread < 0) {
fprintf(stderr, "error echo_read");
return;
}
// print the response buf content
printf("result: %s\n", buf.base);
}
// allocate the receive buffer, suggested_size is the buffer size
// which you want to allocte
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t suggested_size) {
return uv_buf_init((char*) malloc(suggested_size), suggested_size);
}
// when finished write to server , this function will invoke
void on_write_end(uv_write_t *req, int status) {
if (status < 0) {
fprintf(stderr, "error on_write_end");
return;
}
// if message write ok, server will response some message ,
// this fuction is start to read the server response message .
uv_read_start(req->handle, alloc_buffer, echo_read);
}
// this is the connect() function's callback you can
// process your logic when connect established .
void on_connect(uv_connect_t *req, int status) {
if (status < 0) {// all error status will lower than zero
fprintf(stderr, "error on_write_end");
return;
}
// send the file name to server, and server will
// response the file's content .
char *message = "hello.txt";
int len = strlen(message);
// create send buffer
char buffer[100];
uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer));
// set message length and message bytes
buf.len = len;
buf.base = message;
// get the connection's handle
uv_stream_t* tcp = req->handle;
// create the writer
uv_write_t write_req;
int buf_count = 1; // set buffers count
uv_write(&write_req, tcp, &buf, buf_count, on_write_end);
}
int main(void) {
// create default loop
loop = uv_default_loop();
// the tcp client for socket io
uv_tcp_t client;
// init socket ,which combine the loop and client
uv_tcp_init(loop, &client);
// create connect address
struct sockaddr_in req_addr = uv_ip4_addr("127.0.0.1", 7000);
// connect request
uv_connect_t connect_req;
// create connect
uv_tcp_connect(&connect_req, &client, req_addr, on_connect);
// run all events which were registed to the loop
return uv_run(loop);
}
hello from file on server!
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
const int backlog = 128;
const int buffer_size = 1024;
uv_fs_t open_req;
uv_fs_t read_req;
uv_tcp_t *client; // tcp struct
void on_new_connection(uv_stream_t *server, int status);
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t suggested_size);
void on_client_read(uv_stream_t *client, ssize_t nread, uv_buf_t buf);
void on_client_write(uv_write_t *req, int status);
void on_file_open(uv_fs_t *req);
void on_file_read(uv_fs_t *req);
// when the new connection create ,this function will be called .
void on_new_connection(uv_stream_t *server, int status) {
if (status == -1) {
fprintf(stderr, "error on_new_connection");
uv_close((uv_handle_t*) client, NULL);
return;
}
// init server tcp holder
client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
uv_tcp_init(uv_default_loop(), client);// init tcp and event loop
// accept
int result = uv_accept(server, (uv_stream_t*) client);
if (result == 0) { // bind success
uv_read_start((uv_stream_t*) client, alloc_buffer, on_client_read);
} else { // error
uv_close((uv_handle_t*) client, NULL);
}
}
// allocate message buffer
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t suggested_size) {
return uv_buf_init((char*) malloc(suggested_size), suggested_size);
}
// when the read event incoming , this function will called .
void on_client_read(uv_stream_t *_client, ssize_t nread, uv_buf_t buf) {
if (nread == -1) {
fprintf(stderr, "error on_client_read");
uv_close((uv_handle_t*) client, NULL);
return;
}
// read the file name , and open the hello.text ,and write back to client
char *filename = buf.base;
int mode = 0;
uv_fs_open(uv_default_loop(), &open_req, filename, O_RDONLY, mode, on_file_open);
}
// finished write to client event,this function will be invoke .
void on_client_write(uv_write_t *req, int status) {
if (status == -1) {
fprintf(stderr, "error on_client_write");
uv_close((uv_handle_t*) client, NULL);
return;
}
// release the req and it's buffer
free(req);
char *buffer = (char*) req->data;
free(buffer);
// close the client connection
uv_close((uv_handle_t*) client, NULL);
}
// read file
void on_file_open(uv_fs_t *req) {
if (req->result == -1) {
fprintf(stderr, "error on_file_read");
uv_close((uv_handle_t*) client, NULL);
return;
}
// read the file content to the write buffer
char *buffer = (char *) malloc(sizeof(char) * buffer_size);
int offset = -1;
read_req.data = (void*) buffer;
uv_fs_read(uv_default_loop(), &read_req, req->result, buffer, sizeof(char) * buffer_size, offset, on_file_read);
uv_fs_req_cleanup(req); // close file
}
// when file read finished , write the file content to client
void on_file_read(uv_fs_t *req) {
if (req->result < 0) {
fprintf(stderr, "error on_file_read");
uv_close((uv_handle_t*) client, NULL);
} else if (req->result == 0) { // read file ok
uv_fs_t close_req;
uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
uv_close((uv_handle_t*) client, NULL);
} else { // read file by file name
uv_write_t *write_req = (uv_write_t *) malloc(sizeof(uv_write_t));
char *message = (char*) req->data;
// write message to client
uv_buf_t buf = uv_buf_init(message, sizeof(message));
buf.len = req->result;
buf.base = message;
int buf_count = 1;
write_req->data = (void*) message;
// write to client
uv_write(write_req, (uv_stream_t*) client, &buf, buf_count, on_client_write);
}
// release file
uv_fs_req_cleanup(req);
}
int main(void) {
uv_tcp_t server;
uv_tcp_init(uv_default_loop(), &server);
struct sockaddr_in bind_addr = uv_ip4_addr("0.0.0.0", 7000);
uv_tcp_bind(&server, bind_addr);
// start listening
int r = uv_listen((uv_stream_t*) &server, backlog, on_new_connection);
if (r) {
fprintf(stderr, "error uv_listen");
return 1;
}
uv_run(uv_default_loop());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment