2011-08-13 57 views
1

這是我的第一個問題,所以你的恩典將不勝感激。我正在嘗試學習用於Unix的C Sockets。作爲我學習的一部分,我嘗試編寫一個簡單的類telnet客戶端,連接到指定端口上的主機,打印從服務器接收到的任何字符,併發送用戶寫入控制檯的任何內容。它收到罰款,但是當我嘗試發送一個字符串,沒有任何反應。然後,當我中斷程序時,我嘗試發送的所有字符串都會被髮送。先謝謝了。我可能只是在愚蠢。C套接字發送()不會發送,直到程序終止

#include <stdio.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <fcntl.h> 

int SetupSock(char *host, char *port) { 
    int s, status; 
    struct addrinfo hints, *res; 
    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    getaddrinfo(host, port, &hints, &res); 
    if((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { 
     printf("Could not create sock...root?\n"); 
     exit(1); 
    } 
    if((status = connect(s, res->ai_addr, res->ai_addrlen)) == -1) { 
     printf("Connect Failed: %s\n", strerror(errno)); 
     printf("%s", strerror(errno)); 
     printf("\n");  
     exit(1); 
    } 
    return s; 
} 

int main (void) { 
    char *host = malloc(100), *port = malloc(20), buf[2], *msg = malloc(1000); 
    struct timeval waitid; 
    fd_set read_flags, write_flags; 
    signal(SIGPIPE, SIG_IGN); 
    int sock, flags; 
    //Input Host and Port 
    printf("Host: "); 
    gets(host); 
    printf("Port: "); 
    gets(port); 
    sock = SetupSock(host, port); 
    flags = fcntl(sock, F_GETFL, 0); 
    fcntl(sock, F_SETFL, flags | O_NONBLOCK); 
    FD_ZERO(&read_flags); 
    FD_ZERO(&write_flags); 
    FD_SET(sock, &read_flags); 
    FD_SET(fileno(stdin), &read_flags); 
    fflush(0); 
    int pid = fork(); 
    if (pid == 0) { 
     int status; 
     close(stdout); 
     while(1) { 
     select(sock + 1, &read_flags, &write_flags, (fd_set*) 0, &waitid); 
     if (FD_ISSET(fileno(stdin), &read_flags)) { 
      gets(msg); 
      if((status = send(sock, msg, strlen(msg), MSG_NOSIGNAL)) == -1) { 
       printf("Send Failed: %s\n", strerror(errno)); 
      } 
     } 
     } 
    } 
    else { 
     close(stdin); 
     while(1) { 
      select(sock + 1, &read_flags, &write_flags, (fd_set*) 0, &waitid); 
      if (FD_ISSET(sock, &read_flags)) { 
       if(recv(sock, &buf, 1, 0) > 0){  
        printf("%s", buf); 
       } 
      } 
     } 
    } 
    close(sock); 
    return 0; 
} 
+0

顯示接收端。 – cnicutar

+0

使用兩個截然不同的進程發送和接收看起來很奇怪。如果你想這樣做,你應該關閉你不使用的stdout/stdin fd。 –

+0

@cnicutar:你可以爲對方使用任何東西。我猜測OP使用了一個來自互聯網的隨機http服務器,這很好。問題出在這個代碼上。 –

回答

1

您的select在這裏只執行一次。它應該在一個循環內。 select只是等待在提供的一組文件描述符上發生事件。 每個事件處理完畢後都應該再次調用它。

+0

在執行'select'後,'fork'開始執行,程序被分成一個進程和一個寫入進程。所以即使那個選擇在那裏也沒用。更多'select's不會增加任何內容。 – cnicutar

+0

@cnicutar:選擇返回的'sock'和'stdin'的狀態將永遠保持不變。很可能是'sock'解鎖了select(或者'stdin'解鎖了它)。在這些情況下,只有一個'gets'或'send'會被執行。所以你應該再次選擇,看看有什麼改變。 –

+0

的確,我沒有注意到'gets'的FD_ISSET。 – cnicutar

0

要覆蓋一個區域,其他答案錯過了:select和stdio 不要混合。由於緩衝區,fileno(stdin)是否可讀,您無法獲得stdin是否可讀的準確結果。