2012-05-22 66 views
0

我想使用原始套接字使用發送器和接收器程序發送字符數組。我能夠在接收端獲得正確的字節數,但打印出的值是垃圾。有人可以幫我在這裏嗎?原始套接字:接收器打印垃圾值

發射機:

int create_raw_socket(char *dev) 
{ 
struct sockaddr_ll sll; 
struct ifreq ifr; 
int fd, ifi, rb; 

bzero(&sll, sizeof(sll)); 
    bzero(&ifr, sizeof(ifr)); 

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 

assert(fd != -1); 

strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ); 
ifi = ioctl(fd, SIOCGIFINDEX, &ifr); 
assert(ifi != -1); 
sll.sll_protocol = htons(ETH_P_ALL); 
sll.sll_family = AF_PACKET; 
sll.sll_ifindex = ifr.ifr_ifindex; 
rb = bind(fd, (struct sockaddr *)&sll,sizeof(sll)); 
assert(rb != -1); 

return fd; 
} 


int SendPacket(char *dev ,unsigned char *send_packet, int packet_len) 
{ 
    int num_sent= 0; 
    int sockaddress = create_raw_socket(dev); 

    if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len) 
    { 

     close(sockaddress); 
      return 0; 
    } 
    else 
    { 
     close(sockaddress); 
     return 1; 
    } 

    } 


int main(int argc, char**argv) 
{ 
    int x,fd,s; 

    char *send_packet="HELLO"; 

    int len = sizeof(send_packet); 

    while(1) 
    { 

    if(!SendPacket((argv[1]), send_packet, len)) 
    perror("Error sending packet"); 
    else 
    printf("Packet sent successfully with payload : %s\n" ,send_packet); 
    } 
    return 0; 
} 

接收機:

int main(int argc, char **argv) 
{ 
struct sockaddr addr; 
int sock_fd, fromlen,s; 
char buf[PACKET_LENGTH]; 
char *dev = argv[1]; 


while(1) 
{ 

    fromlen=sizeof(addr); 
    sock_fd = create_raw_socket(dev); /* Creating the raw socket */ 
    int x= recvfrom(sock_fd,&buf,sizeof(buf),0,&addr,&fromlen); 
    printf("\n Number of bytes of data received is %d \n",x); 

    printf("\nPayload Received from client... is %s \n", buf); 

    close(sock_fd); 

} 
return 0; 
} 

回答

2

變化

write(sockaddress, &send_packet, packet_len) 

write(sockaddress, send_packet, packet_len) 

send_packet已經是緩衝區的地址發送,如果你把這個地址的地址(更準確地說是變量持有的地址地址),您將讀取緩衝區的錯誤內存

同樣對於recvfrom

recvfrom(sock_fd, buf, sizeof(buf), 0, &addr, &fromlen) 
+0

這對'write'調用是正確的,因爲'send_packet'是一個指針,但對'recvfrom'的調用沒有什麼區別,因爲'buf'是一個數組。數組類型具有這樣的屬性,即它們的地址在數值上等同於它們的第一個元素的地址,所以對於數組'x',總是這樣:'(void *)&x ==(void *)&x [0]'。 –

+0

謝謝@Attila和亞當,它像一個魅力:) – hektor

0

用printf打印緩衝器將打印一個字符串達到串字符的連接直到。如果您看到原始字符串後跟垃圾字符,則可能是原因。

您應該在recvfrom返回的最後一個字節之後引入一個0,否則您將打印recvfrom未覆蓋的內存中的任何值。它甚至可以嘗試訪問緩衝區之外的內存。

嘗試添加類似:

int x= recvfrom(sock_fd,&buf,sizeof(buf) - 1,0,&addr,&fromlen); 
buf[x - 1] = 0; 

注:改變的是什麼讀取的最大尺寸,它僅僅是如何做到這一點的例子。

2

你有幾個問題:

  1. 此行

    if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len) 
    

    應該說的只是send_packet代替&send_packetsend_packet是一個指向所需數據包數據的指針,所以不需要使用它的地址 - 你不想將該指針的文字地址寫入數據包,這根本就行不通。

  2. 這是錯誤的:

    char *send_packet="HELLO"; 
    int len = sizeof(send_packet); 
    

    sizeof(send_packet)永遠是你的系統,通常是4或8個字節上的指針的大小。您確實想要將send_packet聲明爲陣列類型(例如char send_packet[] = ...),或者使用strlen來計算運行時的長度(例如int len = strlen(send_packet) + 1;)。在你的情況下,你要麼發送太少的數據(4字節)或太多的數據(8字節),這兩者都是有問題的。

  3. 您的printf客戶端的代碼假定它收到的數據是空終止的,不一定是這樣。您應該在打印數據之前手動對數據進行空終止處理(或者使用任何其他字符串函數),或者告訴打印多少數據的限制。我建議空的結束它像這樣:

    char buf[PACKET_LENGTH + 1]; // +1 for null terminator 
    int x = recvfrom(sock_fd,buf,PACKET_LENGTH,0,&addr,&fromlen); 
    if(x >= 0) 
        buf[x] = 0; 
    
  4. 你的代碼中有差const正確性。 SendPacket應取const char*而不是char*參數,並且send_packet應宣佈爲char[]const char*。從字符串文字到char*的轉換已被棄用,應該在所有新的C代碼中避免。

+0

感謝您指出了所有的問題。將在我的代碼中糾正它。再次感謝。 – hektor