基于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);;
}
相关文章推荐
- 基于Socket的TCP长连接(服务端Java+客户端Android),Service配合AIDL实现
- Netty实现长连接服务端跟客户端,使用单独的业务线程池,并支持心跳
- vc++实现的tcp socket客户端和服务端示例
- 没有任何关闭socket的日志,客户端和服务端进程都在, 网络连接完好, 为什么进行某操作后好好的tcp连接莫名其妙地断了呢?
- 编写一段Socket服务端程序,监听端口8888,接受到Client的消息“nihao”后,将“nihao”写回到客户端,关闭socket。
- socket编程之TCP服务端与客户端实现
- linux epoll机制对TCP 客户端和服务端的监听C代码通用框架实现
- Java Socket实现多个客户端连接同一个服务端
- java实现socket客户端连接服务端
- 【socket编程】 一个简单的基于TCP连接的客户端、服务端用例
- 使用TCP协议编写一个网络程序,设置服务器端的监听端口是8002,当与客户端建立连接后,服务器端向客户端发送数据“Hello, world”,客户端收到数据后打印输出。
- 没有任何关闭socket的日志,客户端和服务端进程都在, 网络连接完好, 为什么进行某操作后好好的tcp连接莫名其妙地断了呢?
- 利用Tcp和socket实现的客户端与服务端的简单通信
- 服务器监听10000端口,客户端输入什么就返回什么给客户端,如果客户端输入了quit,客户端就与服务端断开连接
- Untiy中用C#实现TCP通讯(Socket通讯)服务端与客户端皆可
- [置顶] 使用多线程实现多客户端的连接(通过Socket实现TCP编程)
- c语言实现socket服务端/客户端通过tcp传送文件
- 使用TCP协议编写一个网络程序,设置服务器端的监听端口是8002,当与客户端建立连接后,服务器端向客户端发送数据“Hello, world”,客户端收到数据后打印输出
- linux网络编程之用socket实现简单客户端和服务端的通信(基于TCP)
- lesson 11:使用TCP协议编写一个网络程序,设置服务器端的监听端口是8002,当与客户端建立连接后,服务器端向客户端发送数据“Hello, world”,客户端收到数据后打印输出。