libuv之开启tcp服务端监听,并获得客户端的ip及端口
2015-02-12 15:17
477 查看
libuv中处理tcp连接的handle叫做uv_tcp_t,可以认为它是uv_stream_t的子类,所以它是可以当作流来使用的,这篇主要内容不在这,其实主要介绍两个函数
一个用来获得“我方”的socket信息,一个用来获得“对方”的socket信息。
下面看一个简单的示例
启动服务器端的监听,我们得到如下输出:
当有一个客户端连接时,输出如下
这两个函数,其实就是对C的两个socket标准函数的封装。
UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen); UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
一个用来获得“我方”的socket信息,一个用来获得“对方”的socket信息。
下面看一个简单的示例
/* * 演示了通过uv_tcp_getpeername获得客户的ip和端口 * test_get_sock_name.cc * Created on: 2015年2月12日 */ #include <stdlib.h> #include <stddef.h> #include <stdio.h> #include <string.h> #include <node/uv.h> int server_port = 7000; uv_tcp_t tcpServer; uv_loop_t* loop; //开启一个tcp监听 int tcp_listener(); //一个新的连接到达时的回调函数 void on_connection(uv_stream_t* server, int status); //校验两个地址是否相同 void check_sockname(struct sockaddr* addr, const char* compare_ip, int compare_port, const char* context); int tcp_listener() { struct sockaddr sockname, peername; int namelen; int r; struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port); uv_tcp_init(loop, &tcpServer); uv_tcp_bind(&tcpServer, addr); uv_listen((uv_stream_t*) &tcpServer, 128, on_connection); //sockname,获得监听自己的ip和端口 memset(&sockname, -1, sizeof sockname); namelen = sizeof sockname; r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen); printf("the r is %d.\n", r); check_sockname(&sockname, "0.0.0.0", server_port, "server socket"); //没有连接时,peername是无意义的 namelen = sizeof peername; r = uv_tcp_getpeername(&tcpServer, &peername, &namelen); printf("the r is %d.\n", r); if (r == -1) { printf("socket is not connected.\n"); } return 0; } void on_connection(uv_stream_t* server, int status) { struct sockaddr sockname, peername; int namelen; uv_tcp_t* handle; int r; if (status != 0) { printf("Connect error %s\n"); } handle = (uv_tcp_t*)malloc(sizeof(*handle)); r = uv_tcp_init(loop, handle); /* associate server with stream */ handle->data = server; uv_accept(server, (uv_stream_t*)handle); memset(&sockname, -1, sizeof sockname); namelen = sizeof sockname; r = uv_tcp_getsockname(handle, &sockname, &namelen); printf("the r is %d.\n", r); check_sockname(&sockname, "0.0.0.0", server_port, "server socket"); //有连接,可以获得目标的ip和端口 namelen = sizeof peername; r = uv_tcp_getpeername(handle, &peername, &namelen); printf("the r is %d.\n", r); check_sockname(&peername, "127.0.0.1", -1, "accepted socket peer"); //这儿应该开启一个流读取数据(这个例子只是为了说明怎么获得客户端的地址和端口) } 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]; int r; struct sockaddr_in compare_addr = uv_ip4_addr(compare_ip, compare_port); /* Both addresses should be ipv4 */ 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"); } /* Check if the ip matches */ if (memcmp(&check_addr.sin_addr, &compare_addr.sin_addr, sizeof compare_addr.sin_addr) == 0) { printf("ip matches.\n"); } /* Check if the port matches. If port == 0 anything goes. */ 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); //或者像下面这样获得ip地址 //char* check_ip = inet_ntoa(check_addr.sin_addr); printf("%s: %s:%d\n", context, check_ip, ntohs(check_addr.sin_port)); } int main() { loop = uv_default_loop(); tcp_listener(); return uv_run(loop, UV_RUN_DEFAULT); }
启动服务器端的监听,我们得到如下输出:
the r is 0. src sin_family is AF_INET. compare sin_family is AF_INET. ip matches. port matches. server socket: 0.0.0.0:7000 the r is -1. socket is not connected.
当有一个客户端连接时,输出如下
the r is 0. src sin_family is AF_INET. compare sin_family is AF_INET. ip matches. port matches. server socket: 0.0.0.0:7000 the r is -1. socket is not connected.
the r is 0.
src sin_family is AF_INET.
compare sin_family is AF_INET.
port matches.
server socket: 127.0.0.1:7000
the r is 0.
src sin_family is AF_INET.
compare sin_family is AF_INET.
ip matches.
accepted socket peer: 127.0.0.1:58830
这两个函数,其实就是对C的两个socket标准函数的封装。
相关文章推荐
- VC++ UDP转TCP互发数据 UDP为服务端 TCP为客户端 可修改IP和端口最小化 2TCP/UDP中转
- 基于libuv实现tcp客户端和服务端(支持监听1000多个端口;打印客户端服务端socket;固定端口连接)
- Xorg服务开启tcp/ip监听,允许其它机器客户端连接
- 配置设置SQL server开启TCP/IP登录,并且启用默认的1433端口配置设置
- 怎样写一个获取数据函数:用TCP/IP通讯,向服务端发送命令,并从服务端获得返回数据.
- 5.3监听请求:使用eclipse的tcp/ip工具(端口转换)
- SQL server开启TCP/IP登录,并且启用默认的1433端口
- VC源码多人网络聊天 TCP服务端向多客户转发 加最小化开机启动参数保存可修改ip和端口版权限制等
- 服务端获得客户端ip
- tcp/ip客户端临时端口
- tcp/ip客户端临时端口
- WebService(2)——使用eclipse的TCP_IP工具监听端口
- TCP/IP?UDP编程之客户端访问服务端的数据库(数据库配置)
- 用java连数据库怎么都连不上,才发现SQL server开启TCP/IP登录,并且启用默认的1433端口
- 监听端口,设置回调接收请求头问题,获取客户端IP
- 解决开启TCP/IP筛选,使用Serv-u 需要开放的端口
- Twisted xmlrpc服务端获得客户端ip的方法
- tcp客户端connect server后,本地端口如何获得
- 编写一段Socket服务端程序,监听端口8888,接受到Client的消息“nihao”后,将“nihao”写回到客户端,关闭socket。
- TCP/IP 多线程服务端多客户端通信 readLine