windows 下libuv编译 及 使用

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

2. 服务端编写
代码如下:
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <uv.h>

#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 <WinSock2.h>
#include <stdio.h>
#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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 下面为Daytime这个服务的源代码例子,同时兼容IPV6和IPV4的地址,最后部分有更多说明。 单播模式下的Se...
    天楚锐齿阅读 5,564评论 0 2
  • 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半相关与全相...
    VD2012阅读 2,268评论 0 5
  • 网络编程基础网络编程,首先了解计算机网络体系结构是有必要的,着重掌握TCP、IP协议,理解socket的概念,理解...
    zhile_doing阅读 1,853评论 0 1
  • 背景 因为最近在研究网络相关的东西,因此经常要写程序做实验来验证。主要是TCP通信,因此就写了个简单的基于TCP通...
    BlueBlueSummer阅读 675评论 0 2
  • socket通信原理 socket又被叫做套接字,它就像连接到两端的插座孔一样,通过建立管道,将两个不同的进程之间...
    jiodg45阅读 1,117评论 0 1