2012-04-18 12 views
0

私はサーバーに接続しているクライアントを書いています。 TCPソケットの124行目memcpy()にSegmentation Faultがあります。 UDP接続では、ネットワーク上のサーバーのIPアドレスを取得したい場合は、IPを取得して、TCP接続を使用して接続します。 TCP接続自体のコードは、新しいファイルでコンパイルすることができるので動作します。問題がどこにあるのか分かりません。memcpy tcpソケットのセグメント障害

#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行目はどこですか?それは伝えにくいです。 –

+0

これは:)申し訳ありません memcpy(&server_addr_tcp.sin_addr、hptr_tcp-> h_addr_list [0]、sizeof(struct in_addr)); – phcaze

+3

以下を実行してください。エラーを表示するのに必要な最小限のコードを減らしてください。エラーが消えるまで一度にコードの一部を削除してから、編集した最後のものを入れてください。コードを減らすと、この方法で絞り込むことができるので、エラーを見つけるのに役立ちます。可能な限り減らしても、エラーを見つけられなかった場合は、縮小コード、予想される出力/動作、および出力/動作を投稿してください。詳細については、http://homepage1.nifty.com/algafield/sscce.htmlを参照してください。 – LiKao

答えて

1

私はgethostbyname()を使用してブロードキャストアドレスを解決することは不可能だと思います。また


gethostbyname()は廃止され、代わりにgetnameinfo()を使用しています。

+0

すべての返信ありがとう、私が解決した瞬間。問題は、クライアントのユーザー名を確認するためのtxtファイルを開く関数でした。私は、if((fp = fopen( "userData.txt"、 "rb +"))== NULL)からif((fp = fopen( "userData.txt"、 "r +"))== NULL) 。現実には、なぜ私がコードの他の部分にあるmemcpyにセグメンテーション違反を与えるのか、まだ理解できません。 – phcaze