您的位置:首页 > 理论基础 > 计算机网络

基于libuv实现tcp客户端和服务端(支持监听1000多个端口;打印客户端服务端socket;固定端口连接)

2018-02-24 17:39 1221 查看

服务端:监听本地1000多个端口;收到连接既接受并打印数据和客户端服务端socket;

github
#include <stdio.h>
#include <stdlib.h>
#include "include/uv.h"

#define DEFAULT_BACKLOG 1000
#define NUM 1000/*1013*/

uv_loop_t *loop;
struct sockaddr_in addr[NUM];
struct sockaddr_in addrCli;
uv_tcp_t server[NUM];

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 echo_write(uv_write_t *req, int status) {
if (status) {
fprintf(stderr, "Write error %s\n", uv_strerror(status));
}
free(req);
}

void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf)
{
if (nread < 0)
{
if (nread != UV_EOF)
printf("Read error %s\n",nread);
uv_close((uv_handle_t*) client, NULL);
return;
}
else if (nread > 0)
{
/*uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
uv_buf_t wrbuf = uv_buf_init(buf->base, nread);
uv_write(req, client, &wrbuf, 1, echo_write);*/
}

struct sockaddr addrlo1;
struct sockaddr_in addrin1;
int addrlen1 = sizeof(addrlo1);
char sockname1[17] = {0};

struct sockaddr addrpeer1;
struct sockaddr_in addrinpeer1;
int addrlenpeer1 = sizeof(addrpeer1);
char socknamepeer1[17] = {0};

int ret1 = uv_tcp_getsockname((const uv_tcp_t *)client,&addrlo1,&addrlen1);
int ret2 = uv_tcp_getpeername((const uv_tcp_t *)client,&addrpeer1,&addrlenpeer1);
if(0 == ret1 && 0 == ret2)
{
addrin1 = *((struct sockaddr_in*)&addrlo1);
addrinpeer1 = *((struct sockaddr_in*)&addrpeer1);
uv_ip4_name(&addrin1,sockname1,addrlen1);
uv_ip4_name(&addrinpeer1,socknamepeer1,addrlenpeer1);
printf("re %s:%d From %s:%d \n",sockname1, ntohs(addrin1.sin_port)/*,buf->base*/,socknamepeer1, ntohs(addrinpeer1.sin_port));
}
else
printf("get socket fail %d %d\n",ret1,ret2);

/*buf->base 需要处理,会影响打印*/
if (buf->base)
free(buf->base);

uv_close((uv_handle_t*) client, NULL);
}

void on_new_connection(uv_stream_t *server, int status) {
if (status < 0)
{
printf("New connection error %s\n", uv_strerror(status));
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) {
uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
// uv_close((uv_handle_t*) client, NULL); 关闭后读不到数据
}
else {
uv_close((uv_handle_t*) client, NULL);
}
}

void creaddr()
{
int i;
for(i = 0;i<NUM;i++)
{
uv_ip4_addr("127.0.0.1",6000+i,&addr[i]);
uv_tcp_init(loop, &server[i]);
uv_tcp_bind(&server[i], (const struct sockaddr*)&addr[i], 0);

if (uv_listen((uv_stream_t*)&server[i], DEFAULT_BACKLOG, on_new_connection))
{
printf("Listen error %d\n",i); //最大支持1014
return;
}
};
}

int main()
{
loop = uv_default_loop();

creaddr();

return uv_run(loop, UV_RUN_DEFAULT);
}

客户端:每20毫秒通过一个固定端口向服务端不同端口发起连接;连接成功既发送数据;打印客户端服务端socket;

github
#include<stdio.h>
#include<stdlib.h>
#include"include/uv.h"

#define NUM 1000
uv_tcp_t server;
#define DEFAULT_BACKLOG 1000

uv_loop_t *loop;
struct sockaddr_in dest[NUM];
static int count = -1;
uv_buf_t writebuf[] = {
{.base = "1",.len = 1},
{.base = "2",.len = 1}
};

uv_buf_t writebuf1[] = {
{.base = "3",.len = 1},
{.base = "4",.len = 1}
};

void creaddr()
{
int i;
for(i = 0;i<NUM;i++)
{
uv_ip4_addr("127.0.0.1",6000+i,&dest[i]);
};
}

void writecb(uv_write_t *req,int status)
{
if(status)
{
printf("write error");
//uv_close((uv_handle_t*)req,NULL);
return;
}

printf("write succeed!");
}

void on_connect(uv_connect_t *req,int status)
{
if(status)
{
printf("connect error");
//uv_close((uv_handle_t*)req,NULL);
return;
}

struct sockaddr addr;
struct sockaddr_in addrin;
int addrlen = sizeof(addr);
char sockname[17] = {0};

struct sockaddr addrpeer;
struct sockaddr_in addrinpeer;
int addrlenpeer = sizeof(addrpeer);
char socknamepeer[17] = {0};

if(0 == uv_tcp_getsockname((uv_tcp_t*)req->handle,&addr,&addrlen) &&
0 ==uv_tcp_getpeername((uv_tcp_t*)req->handle,&addrpeer,&addrlenpeer))
{
addrin = *((struct sockaddr_in*)&addr);
addrinpeer = *((struct sockaddr_in*)&addrpeer);
uv_ip4_name(&addrin,sockname,addrlen);
uv_ip4_name(&addrinpeer,socknamepeer,addrlenpeer);
printf("%s:%d sendto %s:%d",sockname, ntohs(addrin.sin_port),socknamepeer, ntohs(addrinpeer.sin_port));
}
else
printf("get socket fail!\n");

printf(" connect succeed!");
}

void cretcpc(uv_timer_t *timer)
{
if(++count >= NUM)
{
uv_timer_stop(timer);
printf("\ntimer stop!");
return;
}

uv_tcp_t *socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop,socket);

struct sockaddr_in addrlocal;
uv_ip4_addr("127.0.0.1",10000,&addrlocal);
uv_tcp_bind(socket, (const struct sockaddr*)&addrlocal, 0);
printf("\nsocket init:%d %d ",count,ntohs(addrlocal.sin_port));

uv_connect_t *connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
if(0 == uv_tcp_connect(connect,socket,(const struct sockaddr*)&dest[count],on_connect))
{
uv_write_t writereq;
uv_write(&writereq,(uv_stream_t*)socket,writebuf,2/*sizeof(writebuf)/sizeof(uv_buf_t)*/,writecb);

//uv_write_t writereq1;
//uv_write(&writereq1,(uv_stream_t*)socket,writebuf1,2/*sizeof(writebuf)/sizeof(uv_buf_t)*/,writecb);
}
else
{
uv_close((uv_handle_t*)socket,NULL);
printf("close socket! %d\n",count);
}
}

int main()
{
loop = uv_default_loop();

creaddr();
uv_timer_t timer;
uv_timer_init(loop,&timer);

uv_timer_start(&timer,cretcpc,1000,20);

return uv_run(loop,UV_RUN_DEFAULT);;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  libuv tcp socket
相关文章推荐