2012-10-29 77 views
-1

直升機,我試圖通過像這樣經由的recvÇ傳遞結構通過插座/ C++

typedef struct t_timeSliceRequest{ 
unsigned int processId; 
unsigned int timeRequired; 
int priority; 
}timeSliceRequest; 

struct t_timeSliceRequest request = { 1,2,1 }; 
sendFlag = send(socketID,(timeSliceRequest *) &request, sin_size ,0); 

和在服務器端

recvFlag = recv(socketID,(timeSliceRequest *) &request,sin_size,0); 

但其接收垃圾,甚至recv的返回-1請幫

這是我的全孔德

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

enum priority_e{ high, normal, low }; 

typedef struct t_timeSliceRequest{ 
    unsigned int processId; 
    unsigned int timeRequired; 
    int priority; 
}timeSliceRequest; 

typedef struct t_TimeSliceResponse { 
    timeSliceRequest original_req; 

    // Unix time stamp of when process was started on server 
    unsigned int time_started; 

    // Waiting and running time till end of CPU bust 
    unsigned int ttl; 

} TimeSliceResponse; 


int main(int argc, char ** argv){ 
    int socketID = 0, clientID = 0; 
    char sendBuffer[1024], recvBuffer[1024]; 
    time_t time; 
    struct sockaddr_in servAddr, clientAddr; 
    struct t_timeSliceRequest request = {1,1,0}; 

memset(sendBuffer, '0', sizeof(sendBuffer)); 
memset(recvBuffer, '0', sizeof(recvBuffer)); 

fprintf(stdout,"\n\n --- Server starting up --- \n\n"); 
fflush(stdout); 

socketID = socket(AF_INET, SOCK_STREAM, 0); 
if(socketID == -1){ 
    fprintf(stderr, " Can't create Socket"); 
    fflush(stdout); 
} 

servAddr.sin_family = AF_INET; 
servAddr.sin_port = htons(5000); 
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); 

int bindID, sin_size, recvFlag; 
bindID = bind(socketID, (struct sockaddr *)&servAddr, sizeof(servAddr)); // Casting sockaddr_in on sockaddr and binding it with socket id 
if(bindID!=-1){ 
    fprintf(stdout," Bind SucessFull"); 
    fflush(stdout); 
    listen(socketID,5); 
    fprintf(stdout, " Server Waiting for connections\n"); 
    fflush(stdout); 
    while(1){ 
     sin_size = sizeof(struct sockaddr_in); 
     clientID = accept(socketID, (struct sockaddr *) &clientAddr, &sin_size); 
     fprintf(stdout,"\n I got a connection from (%s , %d)", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); 
     fflush(stdout); 
     sin_size = sizeof(request); 
     recvFlag = recv(socketID, &request,sin_size,0); 
     perror("\n Err: "); 
     fprintf(stdout, "\n recvFlag: %d", recvFlag); 
     fprintf(stdout, "\n Time Slice request received:\n\tPid: %d \n\tTime Required: %d ", ntohs(request.processId), ntohs(request.timeRequired)); 
     fflush(stdout); 
     snprintf(sendBuffer, sizeof(sendBuffer), "%.24s\n", ctime(&time)); 
     write(clientID, sendBuffer, strlen(sendBuffer)); 
     close(clientID); 
     sleep(1); 
    } 
}else{ 
    fprintf(stdout, " Unable to Bind"); 
} 
close(socketID); 
return 0; 
} 

和客戶端代碼是:

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

enum priority_e{ high = +1, normal = 0, low = -1}; 

typedef struct t_timeSliceRequest{ 
    unsigned int processId; 
    unsigned int timeRequired; 
    int priority; 
}timeSliceRequest; 

int main(int argc, char *argv[]) 
{ 
    int socketID = 0 /*Socket Descriptor*/, n = 0; 
    char recvBuffer[1024]; 
    memset(recvBuffer, '0',sizeof(recvBuffer)); 
    struct sockaddr_in servAddr; 

    struct t_timeSliceRequest request = { 1,2,high }; 

    if(argc!=2){ 
     fprintf(stderr,"\n Usage: %s <ip of server> \n",argv[0]); 
     return 1; 
    } 

    socketID = socket(AF_INET, SOCK_STREAM, 0); 
    if(socketID == -1){ 
     fprintf(stderr, "\n Can't create socket \n"); 
     return 1; 
    } 

    servAddr.sin_family = AF_INET; 
    servAddr.sin_port = htons(5000); 

    if(inet_pton(AF_INET, argv[1], &servAddr.sin_addr)==-1){ 
     fprintf(stderr, "\n Unable to convert given IP to Network Form \n inet_pton Error"); 
     return 1; 
    } 

    int connectFlag, sendFlag = 0; 
    connectFlag = connect(socketID, (struct sockaddr *)&servAddr, sizeof(servAddr)); 
    if(connectFlag == -1){ 
     fprintf(stderr, " Connection Failed\n"); 
     return 1; 
    } 

    int sin_size = sizeof(struct t_timeSliceRequest); 
    fprintf(stdout, " \n %d \n %d \n %d", request.processId, request.timeRequired, request.priority); 
    sendFlag = send(socketID, &request, sin_size ,0); 
    fprintf(stdout, "\nSend Flag: %d\n", sendFlag); 

    n = read(socketID, recvBuffer, sizeof(recvBuffer)-1); 
    recvBuffer[n] = 0; 
    fprintf(stdout, "%s",recvBuffer); 
    if(n < 0){ 
     fprintf(stderr, " Read error\n"); 
    } 
    return 0; 
} 

這是完整的代碼,它給予「交通運輸端點沒有連接」返回

+0

你可以檢查'errno'(或調用'perror'並查看其結果)在'recv'返回-1之後嗎? –

+0

當我這樣做這樣做 'perror(recvFlag)' 它給服務器 分段錯誤和讀取客戶端上的錯誤,我從來沒有使用'perror' –

+0

只需使用perror(「我們的錯誤信息:」) ',例如,或者簡單的'perror(NULL)',它不會在打印的錯誤消息中添加任何內容。 –

回答

0

交通運輸端點沒有連接錯誤,當你的插座沒有被綁定到任何(端口,地址)對。

如果它是一個服務器端,你應該使用由accept調用返回的套接字描述符。如果是客戶端 - 您應該使用由connect成功調用返回的套接字。

順便說一句,送結構你的方式是相當危險的。編譯器可能會在結構成員之間插入填充字節(程序不可見,但它們會佔用結構中的空間)以符合目標平臺的某些對齊規則。此外,不同的平臺可能會有不同的字節順序,這可能會完全影響您的結構。如果您的客戶端和服務器針對不同的機器進行編譯,則結構佈局和字節序可能不兼容。爲了解決這個問題,你可以使用包裝結構。將結構聲明爲打包的方式取決於編譯器。對於GCC,這可以通過將special attribute添加到結構來完成。

的另一種方法來解決這一問題是手動的結構的每個單獨字段付諸原始字節的緩衝區。接收端應該以與數據最初放入該緩衝區完全相同的方式取出所有這些數據。這種方法可能非常棘手,因爲在保存多字節值(如int,long等)時需要考慮網絡字節順序。有沒有像htonlhtonsntohs等爲一組特殊的功能。

更新

在您的服務器:

recvFlag = recv(socketID, &request,sin_size,0); 

這應該是

recvFlag = recv(clientID, &request,sin_size,0); 

socketID是一種被動的插座,只能接受連接(不發送任何數據)。

更重要的是,中accept結果不檢查-1。

+0

將原來的帖子加入我的代碼...請看看 –

+0

謝謝,問題解決了,工作完美:) –

3

請記住,通過網絡發送結構這樣可能會導致互操作性問題:

  1. 如果源和目標有不同的字節順序,你會收到錯誤的數據(考慮使用像htonl到功能將數據轉換到網絡字節序)
  2. 您結構需要進行包裝,否則不同的編譯器可以對準不同的結構(見this的變量進行了解有關對齊變量)

在任何情況下,ENOTCONN都建議在兩臺主機之間建立連接時出現錯誤。

+0

我用'ntohs()'功能來翻譯,我面臨的主要問題是'recv'返回-1,但連接建立,它發送/接收其他請求,但如果我打包一個結構會失敗。 讓我用我的文章添加我的完整代碼,它會使它更加清晰 –

+0

將我的代碼添加到原始文章中... –