libuv中处理tcp连接的handle叫做uv_tcp_t,可以认为它是uv_stream_t的子类,所以它是可以当作流来使用的,这篇主要内容不在这,其实主要介绍两个函数
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);
下面看一个简单的示例
/*
* 演示了通过uv_tcp_getpeername获得客户的ip和端口
* test_get_sock_name.cc
* Created on: 2015年2月12日
*/
#include
#include
#include
#include
#include
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