2012-04-18 72 views
0

我在寫一個連接到服務器的客戶端。我在TCP套接字的第124行memcpy()上出現了分段錯誤。 通過UDP連接我想獲取網絡上的服務器的IP地址,然後,獲得IP,我想通過TCP連接與它連接。它自己的TCP連接的代碼,因爲我可以編譯一個新文件。我不明白問題在哪裏。memcpy tcp socket上的段錯誤

#include <stdio.h>  
#include <sys/types.h> 
#include <ifaddrs.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <memory.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <sys/types.h> 
#include <netdb.h> 
#include "main.h" 

int developer=1; 
struct myHelloMsg { 
    char myIp[25]; 
    char myID[25]; 
}; 
int FindMyIp(char myIpAddr[], char myMask[], char myBroad[]); 
int RecvBroadTime(int sockfd, struct sockaddr_in server_addr); 
void CheckID(char myUserID[]); 

int main() { 
    char myIpAddr[25], myMask[25], myBroad[25], myUserID[25]=""; 
    char otherUserIp[25], otherUserID[25]; 
    struct myHelloMsg myMsg, rxMsg; 
    CheckID(myUserID); 
    int checkConnection; 
    disconnected: ; 
    checkConnection=0; 
    if (developer==1) printf("\nSearching for a network..\n"); 
    while (checkConnection == 0) { 
     checkConnection = FindMyIp(myIpAddr, myMask, myBroad); 
     if (checkConnection==0) { 
      if (developer==1) printf("--Disconnected..\n"); 
      sleep(5); 
     } 
    } 
    if (developer==1) printf("\n--Connected..\nIP Address\t: %s\n", myIpAddr); 
    if (developer==1) printf("Subnet Mask\t: %s\n", myMask); 
    if (developer==1) printf("Broadcast IP\t: %s\n", myBroad); 

    int i=0; 
    for (i=0;i<25;i++) { 
     myMsg.myIp[i]=myIpAddr[i]; 
     myMsg.myID[i]=myUserID[i]; 
    } 
    struct hostent *hptr = gethostbyname(myBroad); 
    if (hptr == NULL) { 
     if (developer==1) printf("Error while transmitting broadcast message..\n"); 
     return 0; 
    } 
    // create socket for initial UDP communication 
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
    struct sockaddr_in server_addr; 
    bzero(&server_addr, sizeof(struct in_addr)); 
    server_addr.sin_family = AF_INET; 
    server_addr.sin_port = htons(5051); 
    server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); 
    memcpy(&server_addr.sin_addr, hptr->h_addr_list[0], sizeof(struct in_addr)); 
    int opt = 1; 
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int)); 
    int error=0; 
    if (developer==1) printf("--Contacting other users in the network..\n"); 
    sendto(sockfd, &myMsg, sizeof(myMsg), 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)); 
    int foundSomeone=0; 
    //try to connect with others for 5 times - because of UDP unreliable connection 
    int countTries=0, received=0, lastTry=0; 
    while (countTries<5) { 
     foundSomeone = RecvBroadTime(sockfd, server_addr); 
     if (foundSomeone == 1) { 
      if (developer==1) printf("An answer has been received..\n"); 
      socklen_t ssize = sizeof(struct sockaddr_in); 
      recvfrom(sockfd, &rxMsg, sizeof(rxMsg), 0, (struct sockaddr *) &server_addr, &ssize); 
      received=1; 
      countTries=5; 
     } 
     else if (foundSomeone == 0) { 
      if (developer==1) printf("Timeout(%d try)..\n", countTries+1); 
      sendto(sockfd, &myMsg, sizeof(myMsg), 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)); 
      if (countTries==4) { 
       lastTry=1; 
      } 
     } 
     else { 
      if (developer==1) printf("--Error..\n"); 
     } 
     countTries++; 
    } 
    if ((lastTry==1)&&(countTries==5)) { 
     foundSomeone = RecvBroadTime(sockfd, server_addr); 
     if (foundSomeone == 1) { 
      if (developer==1) printf("An answer has been received..\n"); 
      socklen_t ssize = sizeof(struct sockaddr_in); 
      recvfrom(sockfd, &rxMsg, sizeof(rxMsg), 0, (struct sockaddr *) &server_addr, &ssize); 
      received=1; 
     } 
     else if (foundSomeone == 0) { 
      if (developer==1) printf("--No one is connected to the current network..\n"); 
     } 
     else { 
      if (developer==1) printf("There has been an error while trying to contact other users..\n"); 
     } 
    } 
    close(sockfd); 
    // someone else is connected to the network 
    // i am gonna behave as a client in during the synchronization step 
    if (received==1) { 
     if (developer==1) printf("Contact made with user %s (%s).\n", myMsg.myID, myMsg.myIp); 
     // check if the user belong to friends i am sharing content with 
     i=0; 
     for (i=0;i<25;i++) { 
      otherUserIp[i]=rxMsg.myIp[i]; 
      otherUserID[i]=rxMsg.myID[i]; 
     } 
     int socktcp = socket(AF_INET, SOCK_STREAM, 0); 
     struct hostent *hptr_tcp = gethostbyname(otherUserIp); 
     struct sockaddr_in server_addr_tcp; 
     bzero(&server_addr_tcp, sizeof(struct sockaddr_in)); 
     server_addr_tcp.sin_family = AF_INET; 
     server_addr_tcp.sin_port = htons(5054); 
     printf("a\n"); 
     memcpy(&server_addr_tcp.sin_addr, hptr_tcp->h_addr_list[0], sizeof(struct in_addr)); 
     printf("a\n"); 
     if (connect(socktcp, (struct sockaddr *) &server_addr_tcp, sizeof(struct sockaddr_in))<0) { 
      printf("-Error..\n"); 
     } else { 
      printf("Connection with %s established.. Ready for synchronization step..\n", otherUserID); 
     } 
    } 

    return 0; 
} 


int RecvBroadTime(int sockfd, struct sockaddr_in server_addr) { 
    fd_set socks; 
    struct timeval t; 
    t.tv_sec = 1; 
    t.tv_usec = 0; 
    FD_ZERO(&socks); 
    FD_SET(sockfd, &socks); 
    return select(sockfd+1, &socks, NULL, NULL, &t); 
} 

int FindMyIp(char myIpAddr[], char myMask[], char myBroad[]) { 
    struct ifaddrs * ifAddrStruct=NULL; 
    struct ifaddrs * ifa=NULL; 
    void * tmpAddrPtr=NULL; 
    getifaddrs(&ifAddrStruct); 
    int i=0, connected=0; 
    ifa = ifAddrStruct; 
    while (i!=1) { 
     if (((ifa ->ifa_addr->sa_family==AF_INET)&&(ifa->ifa_name[0]=='e')&&(ifa->ifa_name[1]=='n')&&(ifa->ifa_name[2]=='1'))||((ifa ->ifa_addr->sa_family==AF_INET)&&(ifa->ifa_name[0]=='e')&&(ifa->ifa_name[1]=='t')&&(ifa->ifa_name[2]=='h')&&(ifa->ifa_name[3]=='0'))) { 
      i=1; 
      connected=1; 
     } else { 
      if (ifa->ifa_next == NULL) return connected; 
      ifa = ifa->ifa_next; 
     } 
    } 
    tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 
    inet_ntop(AF_INET, tmpAddrPtr, myIpAddr, INET_ADDRSTRLEN); 
    tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 
    inet_ntop(AF_INET, tmpAddrPtr, myMask, INET_ADDRSTRLEN); 
    tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr; 
    inet_ntop(AF_INET, tmpAddrPtr, myBroad, INET_ADDRSTRLEN); 
    return connected; 
} 

void CheckID(char myUserID[]) { 
    FILE *fp; 
    if((fp=fopen("userData.txt", "r+"))==NULL) { 
     printf("Error while opening the file..\n"); 
    } 
    else { 
     fscanf(fp, "%25s", myUserID); 
     if (strlen(myUserID)==0) { 
      printf("First time you open this app..\nInsert your User ID: "); 
      scanf("%s", myUserID); 
      fprintf(fp, "%-25s", myUserID); 
     } 
     else { 
      printf("Welcome back %s..\n", myUserID); 
     } 
     fclose(fp); 
    } 
} 
+0

您發佈的代碼中的第124行在哪裏?很難說。 – 2012-04-18 15:56:33

+0

This one :)對不起 memcpy(&server_addr_tcp.sin_addr,hptr_tcp-> h_addr_list [0],sizeof(struct in_addr)); – phcaze 2012-04-18 15:57:50

+3

請執行以下操作:將代碼降至最低程度,以顯示錯誤。嘗試一次刪除部分代碼,直到錯誤消失,然後將最後編輯的內容放回。減少代碼,已經可以幫助您查找錯誤,因爲您可以通過這種方式縮小代碼。如果您儘可能減少並仍未發現錯誤,請發佈簡化的代碼,預期的輸出/行爲以及您所獲得的輸出/行爲。有關更多信息,請參閱http://homepage1.nifty.com/algafield/sscce.html。 – LiKao 2012-04-18 16:00:27

回答

1

我想說使用gethostbyname()解決廣播地址是不可能的。


另外:gethostbyname()已經過時了,用getnameinfo()代替。

+0

感謝所有的答覆,在我解決問題的那一刻。問題是打開一個用於檢查客戶端用戶名的txt文件的函數。我通過從if((fp = fopen(「userData.txt」,「r +」))== NULL)到if((fp = fopen(「userData.txt」,「rb +」)== NULL) 。實際上,我仍然不明白爲什麼它會在該memcpy上出現段錯誤,這是該代碼的其他部分。 – phcaze 2012-04-18 17:36:52