Explorar el Código

add socketpair

ithewei hace 6 años
padre
commit
15b6a2f2c4
Se han modificado 4 ficheros con 97 adiciones y 0 borrados
  1. 1 0
      Makefile
  2. 69 0
      base/hsocket.c
  3. 3 0
      base/hsocket.h
  4. 24 0
      unittest/socketpair_test.c

+ 1 - 0
Makefile

@@ -69,6 +69,7 @@ curl: prepare
 unittest: prepare
 	$(CC)  -std=c99   -I. -Ibase         -o bin/ping       unittest/ping_test.c          base/hsocket.c base/htime.c -DPRINT_DEBUG
 	$(CC)  -std=c99   -I. -Ibase         -o bin/connect    unittest/connect_test.c       base/hsocket.c base/htime.c
+	$(CC)  -std=c99   -I. -Ibase         -o bin/socketpair unittest/socketpair_test.c    base/hsocket.c base/htime.c
 	$(CXX) -std=c++11 -I. -Ibase         -o bin/defer      unittest/defer_test.cpp
 	$(CXX) -std=c++11 -I. -Ibase         -o bin/threadpool unittest/threadpool_test.cpp  -pthread
 	$(CXX) -std=c++11 -I. -Ibase         -o bin/ls         unittest/listdir_test.cpp     base/hdir.cpp base/hbase.c

+ 69 - 0
base/hsocket.c

@@ -170,6 +170,75 @@ error:
     return socket_errno() > 0 ? -socket_errno() : -1;
 }
 
+int Socketpair(int family, int type, int protocol, int sv[2]) {
+#ifdef OS_UNIX
+    if (family == AF_UNIX) {
+        return socketpair(family, type, protocol, sv);
+    }
+#endif
+    if (family != AF_INET || type != SOCK_STREAM) {
+        return -1;
+    }
+    int listenfd, connfd, acceptfd;
+    listenfd = connfd = acceptfd = INVALID_SOCKET;
+    struct sockaddr_in localaddr;
+    socklen_t addrlen = sizeof(localaddr);
+    memset(&localaddr, 0, addrlen);
+    localaddr.sin_family = AF_INET;
+    localaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    localaddr.sin_port = 0;
+    // listener
+    listenfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (listenfd < 0) {
+        perror("socket");
+        goto error;
+    }
+    if (bind(listenfd, (struct sockaddr*)&localaddr, addrlen) < 0) {
+        perror("bind");
+        goto error;
+    }
+    if (listen(listenfd, 1) < 0) {
+        perror("listen");
+        goto error;
+    }
+    if (getsockname(listenfd, (struct sockaddr*)&localaddr, &addrlen) < 0) {
+        perror("getsockname");
+        goto error;
+    }
+    // connector
+    connfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (connfd < 0) {
+        perror("socket");
+        goto error;
+    }
+    if (connect(connfd, (struct sockaddr*)&localaddr, addrlen) < 0) {
+        perror("connect");
+        goto error;
+    }
+    // acceptor
+    acceptfd = accept(listenfd, (struct sockaddr*)&localaddr, &addrlen);
+    if (acceptfd < 0) {
+        perror("accept");
+        goto error;
+    }
+
+    closesocket(listenfd);
+    sv[0] = connfd;
+    sv[1] = acceptfd;
+    return 0;
+error:
+    if (listenfd != INVALID_SOCKET) {
+        closesocket(listenfd);
+    }
+    if (connfd != INVALID_SOCKET) {
+        closesocket(connfd);
+    }
+    if (acceptfd != INVALID_SOCKET) {
+        closesocket(acceptfd);
+    }
+    return -1;
+}
+
 #define PING_TIMEOUT    1000 // ms
 int Ping(const char* host, int cnt) {
     static uint16_t seq = 0;

+ 3 - 0
base/hsocket.h

@@ -159,6 +159,9 @@ int ConnectNonblock(const char* host, int port);
 #define DEFAULT_CONNECT_TIMEOUT 5000 // ms
 int ConnectTimeout(const char* host, int port, int ms DEFAULT(DEFAULT_CONNECT_TIMEOUT));
 
+// Just implement Socketpair(AF_INET, SOCK_STREAM, 0, sv);
+int Socketpair(int family, int type, int protocol, int sv[2]);
+
 // @param cnt: ping count
 // @return: ok count
 // @note: printd $CC -DPRINT_DEBUG

+ 24 - 0
unittest/socketpair_test.c

@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+#include "hsocket.h"
+
+int main(int argc, char* argv[]) {
+    int sockfds[2];
+    if (Socketpair(AF_INET, SOCK_STREAM, 0, sockfds) != 0) {
+        printf("socketpair failed!\n");
+        return -1;
+    }
+    printf("Socketpair %d<=>%d\n", sockfds[0], sockfds[1]);
+
+    char sendbuf[] = "hello,world!";
+    char recvbuf[1460];
+    int nsend = send(sockfds[0], sendbuf, strlen(sendbuf), 0);
+    printf("sockfd:%d send %d bytes: %s\n", sockfds[0], nsend, sendbuf);
+    memset(recvbuf, 0, sizeof(recvbuf));
+    int nrecv = recv(sockfds[1], recvbuf, sizeof(recvbuf), 0);
+    printf("sockfd:%d recv %d bytes: %s\n", sockfds[1], nrecv, recvbuf);
+
+    closesocket(sockfds[0]);
+    closesocket(sockfds[1]);
+    return 0;
+}