当前位置:编程学习 > C/C++ >>

一种简单的跨平台套接字管道

  socket pair,也称套接字管道,主要用来实现进程内或进程间的一对一的全双工或半双工通信,在IO复用模型(如select,poll,epoll等)中起到通知中断退出循环的作用,在类UNIX系统中已经有现成的实现,API为socketpair,但在WINDOWS系统中没有,因此本文主要讲述WINDOWS平台下soketpair的实现,支持IPv4和IPv6下的tcp、udp套接字管道。对tcp的实现原理是一端在回环地址和某端口上监听接受另一端的连接;而udp的实现原理是先在两端各自绑定回环地址和某端口,然后设定对端地址(调用connect实现)。绑定的回环地址在IPv4和IPv6下分别是127.0.0.1、0:0:0:0:0:0:0:1,而端口由系统分配。

接口
 1#ifdef __cplusplus
 2extern "C" {
 3#endif
 4
 5#ifdef WIN32
 6#include <winsock2.h>
 7#pragma comment(lib,"ws2_32.lib")
 8#endif
 9
10#ifdef WIN32
11#define socket_t SOCKET
12#else
13#define socket_t int
14#endif
15
16  int socket_pair(int family,int type,int protocol,socket_t sock[2]);
17
18#ifdef __cplusplus
19}
20#endif

实现
  1#ifdef WIN32
  2#include <ws2tcpip.h>
  3
  4static int __stream_socketpair(struct addrinfo* ai,socket_t sock[2])
  5{
  6    SOCKET listener,client = INVALID_SOCKET,server = INVALID_SOCKET;
  7    int opt = 1;
  8
  9    listener = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol);
 10    if (INVALID_SOCKET==listener)
 11        goto fail;
 12
 13    setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt, sizeof(opt));
 14
 15    if(SOCKET_ERROR==bind(listener,ai->ai_addr,ai->ai_addrlen))
 16        goto fail;
 17
 18    if (SOCKET_ERROR==getsockname(listener,ai->ai_addr,(int*)&ai->ai_addrlen))
 19        goto fail;
 20
 21    if(SOCKET_ERROR==listen(listener,SOMAXCONN))
 22        goto fail;
 23
 24    client = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol);
 25    if (INVALID_SOCKET==client)
 26        goto fail;
 27
 28    if (SOCKET_ERROR==connect(client,ai->ai_addr,ai->ai_addrlen))
 29        goto fail;
 30
 31    server = accept(listener,0,0);
 32    if (INVALID_SOCKET==server)
 33        goto fail;
 34
 35    closesocket(listener);
 36    sock[0] = client, sock[1] = server;
 37    return 0;
 38
 39fail:
 40    if(INVALID_SOCKET!=listener)
 41        closesocket(listener);
 42    if (INVALID_SOCKET!=client)
 43        closesocket(client);
 44    return -1;
 45}
 46
 47static int __dgram_socketpair(struct addrinfo* ai,SOCKET sock[2])
 48{
 49    SOCKET client = INVALID_SOCKET,server=INVALID_SOCKET;
 50    struct addrinfo addr,*res = NULL;
 51    const char* address;
 52    int opt = 1;
 53
 54    server = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol);
 55    if (INVALID_SOCKET==server)
 56        goto fail;
 57
 58    setsockopt(server,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt, sizeof(opt));
 59
 60    if(SOCKET_ERROR==bind(server,ai->ai_addr,ai->ai_addrlen))
 61        goto fail;
 62
 63    if (SOCKET_ERROR==getsockname(server,ai->ai_addr,(int*)&ai->ai_addrlen))
 64        goto fail;
 65
 66    client = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol);
 67    if (INVALID_SOCKET==client)
 68        goto fail;
 69
 70    memset(&addr,0,sizeof(addr));
 71    addr.ai_family = ai->ai_family;
 72    addr.ai_socktype = ai->ai_socktype;
 73    addr.ai_protocol = ai->ai_protocol;
 74
 75    if (AF_INET6==addr.ai_family)
 76        address = "0:0:0:0:0:0:0:1";
 77    else
 78        address = "127.0.0.1";
 79
 80    if (getaddrinfo(address,"0",&addr,&res))
 81        goto fail;
 82
 83    setsockopt(client,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt, sizeof(opt));
 84    if(SOCKET_ERROR==bind(client,res->ai_addr,res->ai_addrlen))
 85        goto fail;
 86
 87    if (SOCKET_ERROR==getsockname(client,res->ai_addr,(int*)&res->ai_addrlen))
 88        goto fail;
 89
 90    if (SOCKET_ERROR==connect(server,res->ai_addr,res->ai_addrlen))
 91        goto fail;
 92
 93    if (SOCKET_ERROR==connect(client,ai->ai_addr,ai->ai_addrlen))
 94        goto fail;
 95
 96    freeaddrinfo(res);
 97    sock[0] = client, sock[1] = server;
 98    return 0;
 99
100fail:
101    if (INVALID_SOCKET!=client)
102        closesocket(client);
103    if (INVALID_SOCKET!=server)
104        closesocket(server);
105    if (res)
106        freeaddrinfo(res);
107    return -1;
108}
109
110static int win32_socketpair(int family,int type,int protocol,socket_t sock[2])
111{
112    const char* address;
113    struct addrinfo addr,*ai;
114    int ret = -1;
115
116    memset(&addr,0,sizeof(addr));
117    addr.ai_family = family;
118    addr.ai_socktype = type;
119    addr.ai_protocol = protocol;
120
121    if (AF_INET6==family)
122        address = "0:0:0:0:0:0:0:1";
123    else
124        address = "127.0.0.1";
125
126    if (0==getaddrin

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,