2012-02-24 43 views
1

我想在C++類中包裝unix套接字api調用,以使它更容易使用。我用C編寫了一個最小的工作示例,並在一個類中複製了代碼。正如你可以從下面看到的,代碼是相同的,無論我是否調用包裝代碼的函數版本或方法版本。看到醜陋的臨時代碼如下:套接字api不工作在一個類裏面

#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 

static int sockfd; 
static int rec_sock; 
static int len; 

typedef struct sockaddr_in sockaddr_in; 
static sockaddr_in addr; 
static sockaddr_in recaddr; 

int ServerSocket_socket(int family, int type, int protocol) 
{ 
    sockfd = socket(AF_INET, SOCK_STREAM, 0) 
    return sockfd; 
} 

void ServerSocket_bind(int port) 
{ 
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_family = AF_INET; 
    addr.sin_port = port; 

    bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 
} 

void ServerSocket_printInfo(void) 
{ 
    len = sizeof(addr); 
    getsockname(sockfd, (struct sockaddr *)&addr, (socklen_t *)&len); 
    printf("ip = %s, port = %d\n", inet_ntoa(addr.sin_addr), (addr.sin_port)); 
} 

void ServerSocket_listen(int backlog) 
{ 
    listen(sockfd, backlog); 
} 

void ServerSocket_accept(void) 
{ 
    rec_sock = accept(sockfd, (struct sockaddr *)(&recaddr), (socklen_t *)&len); 
} 

void ServerSocket_printPeerInfo(void) 
{ 
    printf("remote machine = %s, port = %x, %x.\n", inet_ntoa(recaddr.sin_addr), recaddr.sin_port, ntohs(recaddr.sin_port)); 
    memset(&recaddr, 0, sizeof(recaddr)); 
    len = sizeof(addr); 
    getpeername(rec_sock, (struct sockaddr *)&recaddr, (socklen_t *) &len); 
} 

void ServerSocket_write(void) 
{ 
    write(rec_sock, "hi, there", 10); 
    sleep(20); 
    exit(1); 
} 

struct ServerSocket 
{ 
    int socket(int family, int type, int protocol) 
    { 
     sockfd = socket(AF_INET, SOCK_STREAM, 0); 
     return sockfd; 
    } 

    void bind(int port) 
    { 
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_family = AF_INET; 
    addr.sin_port = port; 

    ::bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 
    } 

    void printInfo(void) 
    { 
     len = sizeof(addr); 
     getsockname(sockfd, (struct sockaddr *)&addr, (socklen_t *)&len); 
     printf("ip = %s, port = %d\n", inet_ntoa(addr.sin_addr), (addr.sin_port)); 
    } 

    void listen(int backlog) 
    { 
     ::listen(sockfd, backlog); 
    } 

    void accept(void) 
    { 
    rec_sock = ::accept(sockfd, (struct sockaddr *)(&recaddr), (socklen_t *)&len); 
    } 

    void printPeerInfo(void) 
    { 
     printf("remote machine = %s, port = %x, %x.\n", inet_ntoa(recaddr.sin_addr), recaddr.sin_port, ntohs(recaddr.sin_port)); 
     memset(&recaddr, 0, sizeof(recaddr)); 
     len = sizeof(addr); 
     getpeername(rec_sock, (struct sockaddr *)&recaddr, (socklen_t *) &len); 
     printf("remote machine = %s, port = %d, %d.\n", inet_ntoa(recaddr.sin_addr), recaddr.sin_port, ntohs(recaddr.sin_port)); 
    } 

    void write(void) 
    { 
    ::write(rec_sock, "hi, there", 10); 
    sleep(20); 
    exit(1); 
    } 
}; 

當我調用函數代碼的工作就像一個冠軍。但是,當我運行包裝在方法中幾乎相同的代碼時,我拒絕了一個連接。任何想法這最簡單的代碼更改是如何導致該示例不起作用?

ServerSocket_socket(AF_INET, SOCK_STREAM, 0); 
    ServerSocket_bind(1031); 
    ServerSocket_printInfo(); 
    ServerSocket_listen(5); 
    ServerSocket_accept(); 
    ServerSocket_printPeerInfo(); 
    ServerSocket_write(); 
    /* 
    ServerSocket sock; 
    sock.socket(AF_INET, SOCK_STREAM, 0); 
    sock.bind(1031); 
    sock.printInfo(); 
    sock.listen(5); 
    sock.accept(); 
    sock.printPeerInfo(); 
    sock.write(); 
    */ 
+0

我在我的真實代碼。爲了簡潔起見,我只是將其刪除。 – 2012-02-25 01:40:11

回答

2

在ServerSocket_bind變化:

addr.sin_port =端口;

addr.sin_port = htons(port);

它應該工作。此外,使用諸如strace調試系統調用(或ltrace的libc中):

strace的-f ./a.out

ltrace ./a.out

+0

感謝您的回覆。我會考慮未來的使用。由於我的客戶端代碼也沒有將端口改爲網絡字節順序,據我所知,這不會是一個問題。我曾嘗試過每一個端口號上都有字節排序的方式,但都沒有任何效果。 – 2012-02-25 01:56:01

2

試試這個:

#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 

typedef struct sockaddr_in sockaddr_in; 

struct ServerSocket 
{ 
    int sockfd; 
    int rec_sock; 

    ServerSocket() 
    { 
    sockfd = -1; 
    rec_sock = -1; 
    } 

    ~ServerSocket() 
    { 
    if (rec_sock != -1) closesocket(rec_sock); 
    if (sockfd != -1) closesocket(sockfd); 
    } 

    void socket(int family, int type, int protocol) 
    { 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    } 

    void bind(int port) 
    { 
    sockaddr_in addr; 
    memset(&addr, 0, sizeof(addr)); 
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(port); 

    ::bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 
    } 

    void printInfo(void) 
    { 
    sockaddr_in addr; 
    memset(&addr, 0, sizeof(addr)); 
    int len = sizeof(addr); 
    getsockname(sockfd, (struct sockaddr *)&addr, (socklen_t *)&len); 
    printf("ip = %s, port = %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 
    } 

    void listen(int backlog) 
    { 
    ::listen(sockfd, backlog); 
    } 

    void accept(void) 
    { 
    rec_sock = ::accept(sockfd, (struct sockaddr *)(&recaddr), (socklen_t *)&len); 
    } 

    void printPeerInfo(void) 
    { 
    sockaddr_in recaddr; 
    memset(&recaddr, 0, sizeof(recaddr)); 
    int len = sizeof(addr); 
    getpeername(rec_sock, (struct sockaddr *)&recaddr, (socklen_t *) &len); 
    printf("remote machine = %s, port = %d.\n", inet_ntoa(recaddr.sin_addr), ntohs(recaddr.sin_port)); 
    } 

    void write(void *data, int len) 
    { 
    ::write(rec_sock, (char*)data, len); 
    } 
}; 

ServerSocket sock; 
sock.socket(AF_INET, SOCK_STREAM, 0); 
sock.bind(1031); 
sock.printInfo(); 
sock.listen(5); 
sock.accept(); 
sock.printPeerInfo(); 
sock.write("hi, there", 10); 
sleep(20); 
exit(1); 
+0

謝謝。這固定了它。我會區別,看看我在做什麼不同。 – 2012-02-25 01:34:39