0
点赞
收藏
分享

微信扫一扫

libuv学习笔记5------TCP客户端的实现

千行 2021-09-27 阅读 167

前一节我们讲到了如何用libuv实现一个TCP服务器,用libuv实现一个客户端与用libuv实现一个TCP服务器极为类似。不同的地方在于不需要进行uv_tcp_bind操作,将uv_listen改为uv_tcp_connect。

实现一个TCP客户端的基本步骤为:

所用到的API为:

下面讲只针对TCP客户端的实现介绍一个新的API函数uv_tcp_connect。

1.uv_tcp_connect函数讲解


struct sockaddr_in addr;
 
uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
 
 
uv_ip4_addr("192.168.65.205",DEFAULT_PORT,&addr);
 
int r = uv_tcp_connect(connect,&mysocket,(const struct sockaddr*)&addr,on_connect);
 
if(r)
{
    fprintf(stderr, "connect error %s\n", uv_strerror(r));
    return 1;
}

2.uv_tcp_connect回调函数介绍

3.传输指定文件给服务器的代码实现

#include <stdio.h>
#include <uv.h>
#include <stdlib.h>
 
uv_loop_t *loop;
#define DEFAULT_PORT 7000
 
uv_tcp_t mysocket;
 
char *path = NULL;
uv_buf_t iov;
char buffer[128];
 
uv_fs_t read_req;
uv_fs_t open_req;
void on_read(uv_fs_t *req);
void on_write(uv_write_t* req, int status)
{
    if (status < 0) 
    {
        fprintf(stderr, "Write error: %s\n", uv_strerror(status));
        uv_fs_t close_req;
        uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
        uv_close((uv_handle_t *)&mysocket,NULL);
        exit(-1);
    }
    else 
    {
        uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, -1, on_read);
    }
}
 
void on_read(uv_fs_t *req)
{
    if (req->result < 0) 
    {
        fprintf(stderr, "Read error: %s\n", uv_strerror(req->result));
    }
    else if (req->result == 0) 
    {
        uv_fs_t close_req;
        // synchronous
        uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
        uv_close((uv_handle_t *)&mysocket,NULL);
    }
    else
    {
        iov.len = req->result;
        uv_write((uv_write_t *)req,(uv_stream_t *)&mysocket,&iov,1,on_write);
    }
}
 
void on_open(uv_fs_t *req)
{
    if (req->result >= 0) 
    {
        iov = uv_buf_init(buffer, sizeof(buffer));
        uv_fs_read(uv_default_loop(), &read_req, req->result,&iov, 1, -1, on_read);
    }
    else 
    {
        fprintf(stderr, "error opening file: %s\n", uv_strerror((int)req->result));
        uv_close((uv_handle_t *)&mysocket,NULL);
        exit(-1);
    }
}
 
void on_connect(uv_connect_t* req, int status)
{
    if(status < 0)
    {
        fprintf(stderr,"Connection error %s\n",uv_strerror(status));
 
        return;
    }
 
    fprintf(stdout,"Connect ok\n");
 
    uv_fs_open(loop,&open_req,path,O_RDONLY,-1,on_open);
 
 
}
 
int main(int argc,char **argv)
{
    if(argc < 2)
    {
        fprintf(stderr,"Invaild argument!\n");
 
        exit(1);
    }
    loop = uv_default_loop();
 
    path = argv[1];
 
    uv_tcp_init(loop,&mysocket);
 
    struct sockaddr_in addr;
 
    uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
 
 
    uv_ip4_addr("127.0.0.1",DEFAULT_PORT,&addr);
 
    int r = uv_tcp_connect(connect,&mysocket,(const struct sockaddr *)&addr,on_connect);
 
    if(r)
    {
        fprintf(stderr, "connect error %s\n", uv_strerror(r));
        return 1;
    }
 
    return uv_run(loop,UV_RUN_DEFAULT);
}

这段代码利用了libuv文件操作、流操作、TCP实现等知识。代码的基本逻辑如下:

1.创建TCP客户端对象,和TCP连接请求对象,并与服务器建立连接。

2.连接成功后打开要传输的文件。

3.打开文件成功后读取一定的文件内容,并在读取成功后将文件内容利用stream操作发送给服务器。

4.发送成功后再次读取文件内容,并在读取成功后发送给服务器。

5.循环进行第4步操作,直到读到文件末尾。

6.关闭文件、关闭流。

测试:

1.打开服务器,监听7000端口,并将输出重定向到文件:

2.编译并运行程序:

举报

相关推荐

0 条评论