windows 下libuv编译 及 使用

build目录下存放gyp目录及内容

2. 服务端编写
代码如下:
#include

#include

#include

#include

#define DEFAULT_PORT 7000

#define DEFAULT_BACKLOG 128

uv_loop_t *loop;

struct sockaddr_in addr;

unsigned int tag_times = 0; // 连续三次收到客户端消息 this is client , 则结束通信

typedef struct {

uv_write_t req;

uv_buf_t buf;

} write_req_t;

// 获取客户端ip, port

void check_sockname(struct sockaddr* addr, const char* compare_ip, int compare_port, const char* context) {

struct sockaddr_in check_addr = *(struct sockaddr_in*) addr;

char check_ip[17] = { 0 };

int r;

struct sockaddr_in compare_addr = { 0 };

int ret = uv_ip4_addr(compare_ip, compare_port, &compare_addr);

if (check_addr.sin_family == AF_INET) {

printf("src sin_family is AF_INET.\n");

}

if (compare_addr.sin_family == AF_INET) {

printf("compare sin_family is AF_INET.\n");

}

if (memcmp(&check_addr.sin_addr, &compare_addr.sin_addr,

sizeof compare_addr.sin_addr) == 0) {

printf("ip matches.\n");

}

if (compare_port == 0 || check_addr.sin_port == compare_addr.sin_port) {

printf("port matches.\n");

}

//网络字节序转换成主机字符序

uv_ip4_name(&check_addr, (char*)check_ip, sizeof check_ip);

printf("%s: %s:%d\n", context, check_ip, check_addr.sin_port);

}

void free_write_req(uv_write_t *req) {

write_req_t *wr = (write_req_t*)req;

free(wr->buf.base);

free(wr);

}

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {

buf->base = (char*)malloc(suggested_size);

buf->len = suggested_size;

}

void on_close(uv_handle_t* handle) {

free(handle);

}

void echo_write(uv_write_t *req, int status) {

if (status) {

fprintf(stderr, "Write error %s\n", uv_strerror(status));

}

free_write_req(req);

}

void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {

if (nread > 0) {

write_req_t *req = (write_req_t*)malloc(sizeof(write_req_t));

req->buf = uv_buf_init(buf->base, nread);

fwrite(buf->base, nread, 1, stdout); // 控制台显示客户端发送过来的内容

fwrite("\n", 1, 1, stdout);

if (strcmp(req->buf.base, "are you ok")==0) {

char ack_msg[] = "server ok";

strcpy(req->buf.base, ack_msg);

req->buf.len = strlen(ack_msg);

uv_write((uv_write_t*)req, client, &req->buf, 1, echo_write); // 往客户端发送内容

}

else if (strcmp(req->buf.base, "this is client") == 0) { // 连续三次收到 this is client 消息,则发送结束标志 finished

tag_times++;

if (tag_times == 3)

{

char ack_msg[] = "finished";

strcpy(req->buf.base, ack_msg);

req->buf.len = strlen(ack_msg);

uv_write((uv_write_t*)req, client, &req->buf, 1, echo_write); // 往客户端发送内容

}

else {

uv_write((uv_write_t*)req, client, &req->buf, 1, echo_write); // 往客户端发送内容

}

}

else {

uv_write((uv_write_t*)req, client, &req->buf, 1, echo_write); // 往客户端发送内容

}

return;

}

if (nread < 0) {

if (nread != UV_EOF)

fprintf(stderr, "Read error %s\n", uv_err_name(nread));

uv_close((uv_handle_t*)client, on_close);

}

free(buf->base);

}

void on_new_connection(uv_stream_t *server, int status) {

if (status < 0) {

fprintf(stderr, "New connection error %s\n", uv_strerror(status));

// error!

return;

}

uv_tcp_t *client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));

uv_tcp_init(loop, client);

//client->data = server;

if (uv_accept(server, (uv_stream_t*)client) == 0) {

//获取客户端 ip和端口

//{

// struct sockaddr peername;

// int namelen, r;

//

// //有连接,可以获得目标的ip和端口

// namelen = sizeof peername;

// r = uv_tcp_getpeername(client, &peername, &namelen);

// printf("the r is %d.\n", r);

// check_sockname(&peername, "127.0.0.1", -1, "accepted socket peer");

//}

uv_read_start((uv_stream_t*)client, alloc_buffer, echo_read);

}

else {

uv_close((uv_handle_t*)client, on_close);

}

}

int main()

{

loop = uv_default_loop();

uv_tcp_t server;

uv_tcp_init(loop, &server);

uv_ip4_addr("192.168.0.25", DEFAULT_PORT, &addr);

uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);

int r = uv_listen((uv_stream_t*)&server, DEFAULT_BACKLOG, on_new_connection);

if (r) {

fprintf(stderr, "Listen error %s\n", uv_strerror(r));

return 1;

}

return uv_run(loop, UV_RUN_DEFAULT);

}

3. 客户端编写
#include
#include
#pragma comment(lib, "ws2_32.lib")
#define NO_FLAGS_SET 0
#define PORT (u_short) 7000
#define DEST_IP_ADDR "192.168.0.25" //Server address

int main()
{

// initial socket library

WORD wVerisonRequested;

WSADATA wsaData;

int err;

wVerisonRequested = MAKEWORD(1, 1);

err = WSAStartup(wVerisonRequested, &wsaData);

if (err != 0)

{

return -1;

}

// create socket

SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

// connect server socket

SOCKADDR_IN addrServer;

addrServer.sin_addr.S_un.S_addr = inet_addr(DEST_IP_ADDR);

addrServer.sin_family = AF_INET;

addrServer.sin_port = htons(PORT);

connect(sockClient, (SOCKADDR *)&addrServer, sizeof(addrServer));

// send

char sendBuf[ ] = "are you ok";

int sended = send(sockClient, sendBuf, strlen(sendBuf) + 1, 0);

// receive

char recvBuf[MAX_PATH] = { 0 };

recv(sockClient, recvBuf, sizeof(recvBuf), 0);

if (strcmp(recvBuf, "server ok") == 0) {

printf("%s\n", recvBuf);

bool is_finished = false;

while (!is_finished) {

char sendBuf[] = "this is client";

int sended = send(sockClient, sendBuf, strlen(sendBuf) + 1, 0);

::Sleep(50);

char recvBuf[MAX_PATH] = { 0 };

recv(sockClient, recvBuf, sizeof(recvBuf), 0);

printf("%s\n", recvBuf);

if (strcmp(recvBuf, "finished") == 0) {

is_finished = true;

}

}

}

printf("%s\n", recvBuf);

closesocket(sockClient);

WSACleanup();

system("pause");

return 0;

}

4. 相关函数解释

服务端: 一般监听时设置 连接到来的回调 ,如下:
int r = uv_listen((uv_stream_t*)&server, DEFAULT_BACKLOG, on_new_connection);

4.1  on_new_connection  如何被调用呢?
答:在tcp.c 文件的 函数 uv_process_tcp_accept_req 中执行了连接到来的回调。

4.2  在连接到来回调函数内部,指定了读到来回调,uv_read_start((uv_stream_t*)client, alloc_buffer, echo_read);  其中:echo_read回调如何被执行呢?
答: 由tcp.c 中 uv_process_tcp_read_req 函数内部调用了读回调。

4.3 服务端写消息函数 uv_write((uv_write_t*)req, client, &req->buf, 1, echo_write);
其中:echo_write 回调如何被执行呢?
答:在tcp.c中,函数 uv_process_tcp_write_req 内部执行了回调echo_write

你可能感兴趣的:(windows 下libuv编译 及 使用)