2012-05-16 80 views
0

我嘗試與TCP服務器/客戶端程序,但不知道爲什麼在服務器端,在程序循環accept()方法返回....TCP服務器不接受來自()

我的想法是開發一個從多個客戶端一次接收1個請求的TCP服務器。完成單個操作後,服務器和客戶端之間的連接應關閉。例如, 1)TCP服務器應始終聽到端口30000。 2)TCP客戶端1連接到TCP服務器,發送「hello」,並等待來自服務器的「hello」反饋,並關閉連接。 3)TCP客戶端2連接到TCP服務器,發送「hello」,並等待來自服務器的「hello」反饋,並關閉連接。 依此類推,直到TCP客戶端Ñ....

上述所有被執行一次一個,這意味着TCP客戶端1和2不會在同一時間發送消息給TCP服務器的操作的,而且一旦TCP客戶端1完成操作後不再連接到服務器(如有必要,可以觸發新的連接)。

輸出顯示

======== NW Test ======= 
1) Start (T)CP Server 
2) Start T(C)P Client 
3) (S)end TCP Message 
4) Close TCP S(O)cket 
0) (Q)uit 
================================ 
Option: t 
Starting TCP server... 
create socket success. 
bind socket success. 
listen socket success. 

我也期待...

accept socket success. 
pthread_create success. 
TCP server started, listening socket [tcpsocket] 

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

struct attr { 
    int tcpsocket; 
}; 

static int nwMenu(); 
static void *event_start(void* param); 

int tcpserver(){ 
    int thread_id; 
    int tcpSocket; 
    int listenSocket; 
int nRet; 
    socklen_t nLen;   
struct attr atr; 
    struct sockaddr_in saTCPServer, saTCPClient; 

fprintf(stderr, "Starting TCP server...\n"); 

    listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (listenSocket < 0) 
    { 
    fprintf(stderr, "fail to create socket.\n"); 
     return -1; 
    } else { 
    fprintf(stderr, "create socket success.\n"); 
} 

    saTCPServer.sin_family = AF_INET; 
    saTCPServer.sin_addr.s_addr = INADDR_ANY; 
    saTCPServer.sin_port = 30000; 

    nRet = bind(listenSocket, (struct sockaddr *) &saTCPServer, sizeof(struct sockaddr)); 
    if (nRet < 0) 
    { 
    fprintf(stderr, "fail to bind socket.\n"); 
     close (listenSocket); 
     return -1; 
    } else { 
    fprintf(stderr, "bind socket success.\n"); 
} 

    if (listen(listenSocket, 5) < 0) { 
    fprintf(stderr, "fail to listen socket.\n"); 
     close (listenSocket); 
     return -1; 
    } else { 
    fprintf(stderr, "listen socket success.\n"); 
} 

    nLen = sizeof(saTCPClient); 

    tcpSocket = accept(listenSocket, (struct sockaddr *) &saTCPClient, &nLen); 
    if (tcpSocket < 0) 
    {  
    fprintf(stderr, "fail to accept socket.\n"); 
     close (listenSocket); 
     return -1;  
    } else { 
    fprintf(stderr, "accept socket success.\n"); 
} 
atr.tcpsocket = tcpSocket; 

    close (listenSocket); 

    if(pthread_create(&thread_id, NULL, (void*) event_start, (void*) &atr) != 0){ 
    fprintf(stderr, "pthread_create failed.\n"); 
} else { 
    fprintf(stderr, "pthread_create success.\n"); 
}; 

fprintf(stderr, "TCP server started, listening socket %d\n", tcpSocket); 

return 0; 

} 

static void *event_start(void* param) { 

    int quit = 0; 
    int nRet = 0; 
int tcpSocket; 
    char szBuf[4096]; 

struct attr *p_atr = (struct attr*)param; 
tcpSocket = p_atr->tcpsocket; 

    while (!quit){ 

     nRet = recv(tcpSocket, szBuf, sizeof(szBuf), 0); 
     if (nRet <= 0) // peer closed 
     { 
      fprintf(stderr, "receiver quit recv\n"); 
     quit = 1; 
     break; 
      } 

     fprintf(stderr, "recv: %s\n", szBuf); 

     send(tcpSocket, szBuf, sizeof(szBuf), 0); 
    } 

    close(tcpSocket); 
} 


int tcpclient(){ 
    int tcpSocket; 
    struct sockaddr_in saTCPServer; 

    bzero((void *) &saTCPServer, sizeof(saTCPServer)); 

    char* szServer = "127.0.0.1"; 
    int nPort = 30000; 

    inet_aton(szServer, &saTCPServer.sin_addr); 

    tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (tcpSocket < 0){ 
     return -1; 
    } else { 
     fprintf(stderr, "client tcp socket: %d\n", tcpSocket); 
    } 

    saTCPServer.sin_family = AF_INET; 
    saTCPServer.sin_port = htons(nPort); 

    if (connect(tcpSocket, (struct sockaddr *) &saTCPServer, sizeof(saTCPServer)) < 0)  { 
     return -1; 
    } 

    fprintf(stderr, "TCP client started, listening socket %d\n", tcpSocket); 

    return 0; 
} 

int send_tcp_msg(int tcpSocket){ 
    int nRet; 
    char szBuf[4096]; 

    memset(szBuf, 0x00, sizeof(szBuf)); 

    send(tcpSocket, "hello", sizeof("hello"), 0); 

    nRet = recv(tcpSocket, szBuf, sizeof(szBuf), 0); 

    fprintf(stderr, "recv: %s\n", szBuf); 

return 0; 
} 

int close_tcp(int tcpSocket){ 
    close(tcpSocket); 

return 0; 
}  

static int nwMenu(){ 
    int ret = 0; 
    int socket; 
    char buff[1024]; 

    do{ 
    fprintf(stderr, "======== NW Test =======\n"); 
    fprintf(stderr, "1) Start (T)CP Server\n"); 
    fprintf(stderr, "2) Start T(C)P Client\n"); 
    fprintf(stderr, "3) (S)end TCP Message\n"); 
    fprintf(stderr, "4) Close TCP S(O)cket\n");  
    fprintf(stderr, "0) (Q)uit\n"); 
    fprintf(stderr, "================================\n"); 
    fprintf(stderr, "Option: "); 
    memset(buff, 0x00, sizeof(buff)); 
    gets(buff); 

    if (buff[0] == 't' || buff[0] == 'T'){   
     ret = tcpserver();   
    } else if (buff[0] == 'c' || buff[0] == 'C'){ 
     ret = tcpclient(); 
    } else if (buff[0] == 'o' || buff[0] == 'O'){ 
     fprintf(stderr, "Enter socket fd:\n"); 
     gets(buff);   
     ret = close_tcp(atoi(buff)); 
    } else if (buff[0] == 's' || buff[0] == 'S'){ 
     fprintf(stderr, "Enter socket fd:\n"); 
     gets(buff);   
     ret = send_tcp_msg(atoi(buff)); 
    } 

    }while(buff[0] != 'q' && buff[0] != 'Q'); 

    return 0; 
} 

int main(int argc, const char* argv[]){ 

    nwMenu(); 

    return 0; 
} 
+1

您的代碼及其消息表明您可能誤解了accept()的用途。當你打電話給你時,你的服務器是有效的。它不會(通常)返回到客戶端連接。您的後續服務器啓動消息應該說,而不是客戶端連接 –

+0

arh ...好的!罪魁禍首是......我在客戶端設置服務器IP地址爲「127.0.0.1」。所以當我試圖連接到服務器時,它失敗了。我將其更改爲eth0 IP(實際:192.168.122.1),並按預期工作。我想知道爲什麼它必須是非回送IP。 – twfx

回答

2

你的服務器做:

saTCPServer.sin_port = 30000; 

這應該是

saTCPServer.sin_port = htons(30000); 

端口在網絡順序指定的,如果你是一個小端機器上,30000並沒有轉化到端口30000,但端口12405.所以你的服務器監聽在與客戶端連接的端口不同的端口上。

+0

注意:你可以用'netstat -tln'來驗證這個 –

+0

我把它改成saTCPServer.sin_port = htons(30000);但結果仍然是相同的.... hmmm – twfx

+0

我從netstat -tln下面得到 - > tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN – twfx

相關問題