2014-03-18 67 views
1

你好我的服務器程序是:Linux的套接字客戶端/服務器程序

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
int main() 
{ 
    int sfd, cfd; 
    int ch='k'; 
    struct sockaddr_in saddr, caddr; 

    sfd= socket(AF_INET, SOCK_STREAM, 0); 
    saddr.sin_family=AF_INET;   /* Set Address Family to Internet */ 
    saddr.sin_addr.s_addr=htonl(INADDR_ANY); /* Any Internet address */ 
    saddr.sin_port=htons(29008);   /* Set server port to 29008 */ 
         /* select any arbitrary Port >1024    */ 
    bind(sfd, (struct sockaddr *)&saddr, sizeof(saddr)); 
    listen(sfd, 1); 
    while(1) { 
      printf("Server waiting..."); 
      cfd=accept(sfd, (struct sockaddr *)NULL, NULL); 
      if(read(cfd, &ch, 1)<0) perror("read"); 
      ch++; 
      if(write(cfd, &ch, 1)<0) perror("write"); 
      close(cfd); 
    } 
} 

,所以我有一個簡單的服務器程序,我也有一個客戶端程序。我遇到的問題是,當我在不同的終端上運行在同一臺機器上時,客戶端輸出工作正常。服務器雖然不打印等待的線路,但它堆疊使我無法使用終端。有什麼問題 ?

+2

您正在使用的輸出機制是* line buffered *,意思是直到發送換行符或調用fflush(stdout)時纔會生成輸出。此外,打開套接字的方式可以防止在沒有完全關閉的情況下立即重新使用套接字,因此後續的程序調用可能無法打開,因爲您的錯誤報告很少,因此可能無法看到。 –

+0

是的。這也是一種「分叉」 - 不是爲了分離接受函數,而是通過某種方式退出該服務器循環的一個好主意。最終每個服務器都想下來,如果他能安裝一個新刀片服務器的唯一方法是通過在服務器程序上按ctrl-c,那麼你將使一些服務器管理員非常緊張。 – ciphermagi

+1

您的客戶是否爲每個發送的字符建立一個新的'connect()'? – alk

回答

2

正如評論指出的那樣,你需要完全依靠stdout操作之前發送一個新的行或fflush(stdout),使服務器打印你想要什麼,或禁用緩衝:setbuf(stdout, NULL),這是沒有必要的。默認情況下,stdout是行緩衝的,stderr是無緩衝的。並且請注意,Microsoft運行時庫不支持行緩衝,因此如果使用Winsock實現此程序,它將立即打印。
bind()之前,您可以設置SO_REUSEADDR選項,以便當程序不乾淨地退出時(在上面的代碼中,您沒有明確關閉偵聽套接字sfd,雖然操作系統在終止時會清理乾淨,但這是一種很好的做法這樣做),可以保持在TIME_WAIT狀態的端口可以立即重新使用。

int yes = 1; 
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) 

如果你想你運行該程序後使用當前的終端,添加&你的命令之後,所以程序會在後臺運行。

+0

呃非常感謝您的信息! – KostasRim