2012-04-18 70 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