2010-03-01 131 views
10

編輯:下面已經固定接收和發送正確並且解釋消息的實際字節代碼發送annd收到(後者由於EJP)Socket編程:RECV /讀取問題

我用Unix編程。

我有服務器和客戶端,都應該更換封郵件。雖然客戶端似乎發送的消息很好,但服務器不會收到客戶端發送的消息。我已經使用recv()read()嘗試(我知道他們是幾乎同樣的事情,但對recv()額外的標誌),但我有沒有運氣,我真的不知道真正的問題是什麼。

我把sleep(3)放在客戶端代碼中,每次它發送一條消息,但我看到一旦客戶端和服務器連接,服務器立即關閉而不等待傳入的消息。我究竟做錯了什麼?

這是客戶端代碼:

#define SERVER_TCP_PORT 11112 
#define MAX_DATA_SIZE 500 

int main(int argc, char * argv[]) 
{ 
    int sockfd; 
    char * host; 
    char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/ 
    int msg_len; 

    struct hostent * hp; 
    struct sockaddr_in client_address, server_address; 


    printf("y halo thar\n"); 


    // looking up from the host database 
    if (argc == 2) 
     host = argv[1]; 
    else 
     exit(1); 
    printf("sdf\n"); 


    hp = gethostbyname(host); 
    if (!hp) 
     exit(1); 
    printf("host found\n"); 


    // setting up address and port structure information 
    bzero((char *) &server_address, sizeof(server_address)); // copy zeroes into string 
    server_address.sin_family = AF_INET; 
    bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length); 
    server_address.sin_port = htons(SERVER_TCP_PORT); 
    printf("set\n"); 


    // opening up socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     exit(1); 
    printf("opened\n"); 


    // connecting 
    if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
     exit(1); 
    printf("connected\n"); 


    int i; 

    for (i = 0; i < MAX_DATA_SIZE; ++i) 
    { 
     msg[i] = '.'; 
    } 

    msg[MAX_DATA_SIZE-1] = '\0'; 

    for(i = 0; i < 11; i++) 
    { 
     // send message to connected socket 
     msg_len = write(sockfd, msg, MAX_DATA_SIZE); 
     if(msg_len < 1) 
      printf("notsent\n"); 
     else 
      printf("%i bytes sent\n", msg_len); 

     // recieve messages from connected socket 
     msg_len = read(sockfd, msg, MAX_DATA_SIZE); 
     if (msg_len < 1) 
      printf("not recieved\n"); 
     else 
     { 
      printf("%i bytes received\n", msg_len); 
      printf(msg); 
      printf("\n"); 

     } 
    } 


    // close connection 
    close(sockfd); 
    printf("closed\n"); 

} 

,這是服務器端

#define SERVER_TCP_PORT 11112 
#define MAX_DATA_SIZE 500 


int main() 
{ 

    printf("o halo thar\n"); 

    int sockfd, new_sockfd; 
    int client_addr_len; 
    char msg [MAX_DATA_SIZE]; 
    int msg_len; 
    char got_msg [11] = "got ur msg\0"; 
    struct sockaddr_in server_address, client_address; 


    // setting up address and port structure information 
    bzero((char *) &server_address, sizeof(server_address)); // copy zeroes into string 
    server_address.sin_family = AF_INET; 
    server_address.sin_addr.s_addr = htonl(INADDR_ANY); 
    server_address.sin_port = htons(SERVER_TCP_PORT); 


    // opening up socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     exit(1); 
    printf("socket is opened\n"); 


    // binding 
    if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
     exit(1); 
    printf("socket is bound\n"); 


    // listening 
    listen(sockfd,5); 
    printf("listening\n"); 

    // block and wait for an incoming connection 

    client_addr_len = sizeof(client_address); 
    new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len); 
    if (new_sockfd < 0) 
     exit(1); 

    printf("accepted\n"); 


    int i; 

    for(i = 0; i < 11; i++) 
    { 
     // recieve messages from connected socket 
     printf("waiting\n"); 
     msg_len = read(new_sockfd, msg, MAX_DATA_SIZE); 
     if (msg_len < 1) 
     { 
      printf("no msg recieved\n");  
     } 
     else 
     { 
      printf("bytes recieved: %i\n", msg_len); 
     } 


     // send message to connected socket 
     msg_len = write(new_sockfd, got_msg, sizeof(got_msg)); 
     if (msg_len < 1) 
      printf("not sent\n"); 
     else 
      printf("%i bytes sent\n", msg_len); 
    } 


    // close connection 
    close(sockfd); 
    printf("socket closed. BYE! \n"); 


} 

回答

10

在服務器代碼,問題是在這條線:

msg_len = read(sockfd, msg, MAX_DATA_SIZE); 

要調用readsockfd,但你需要調用new_sockfdreadrecv(由accept()返回的插座)。 new_sockfd是連接到客戶端(sockfd用於接受更多的連接 - 例如,如果另一個客戶端連接)。

+0

謝謝你解決了這個問題!而且,從accept()中讀取新的套接字文件描述符會更有意義。 – 2010-03-01 05:37:23

+2

除了檢查錯誤以外,您還忽略了read()和write()()返回的計數。你不能那樣做:你必須使用它們來確定實際讀取或寫入的數據量。你不能假設你的請求已經完成。 – EJP 2010-03-01 05:45:23

+0

EJP現在的代碼確實發送和接收的消息的實際字節數。謝謝。 – 2010-03-01 07:01:12

-1

是基於流或數據報執行?

也有一些問題,您的操作流程。服務器可能在客戶端發送任何內容之前開始讀取。

,因爲客戶端和服務器是分開的,你能想象他們同時運行。 在服務器端「接受」連接請求後,可能會出現一些握手開銷或網絡延遲,導致服務器應用程序提前執行,嘗試提取數據但遇到錯誤(尚未收到數據)。 接受連接後,您可以通過在服務器代碼中添加睡眠來嘗試此操作,其中客戶端應該有足夠的時間來發送數據。

另一個較好的解決方案是使數據檢索應付空緩衝器或異步讀取。

+0

沒有與服務器調用完全沒有問題'客戶端之前read'發送任何東西。只有數據可用時,「read」調用纔會被阻塞。 「尚未收到數據」是**不是**錯誤。 – caf 2010-03-01 05:33:39

+0

而且不需要睡覺。 – EJP 2010-03-01 06:42:27

+0

我只在客戶端添加sleep()以找出問題所在,但實際上不能(也不應該)使用sleep(),因爲此程序的目的是測量數據包往返行程。 – 2010-03-01 07:02:56

0

你應該從accept返回的套接字讀取。

嘗試致電readsocketaccept返回。

+0

客戶端發送的消息明確以「。」字符開頭。 – caf 2010-03-01 05:32:33

+0

哦,我在看代碼的錯誤部分 – stefanB 2010-03-01 05:34:26

0

發送端:

while(!feof(fp)) 
{ 
    len=fread(buff,sizeof(char),MW,fp); 
    if(len==0) 
    { 
     //EOF 
     st=write(cd,&d,sizeof(int));  
     break; 
    } 
    else 
    { 
     st=write(cd,buff,len); 
    } 
} 
0

接收側:

while(1) 
    {  
     len=read(sd,buff,sizeof(buff)); 

     if(len==0) 
     { 
      //End of File receving.    

      break; 
     } 
     else  
     { 
      st=fwrite(buff,sizeof(char),len,fp); 

     } 
    }