0

我正在编写一个连接到服务器的客户端。我在 TCP 套接字的第 124 行 memcpy() 上遇到了分段错误。使用 UDP 连接我想获取网络上服务器的 IP 地址,然后,获得 IP,我想通过 TCP 连接与其连接。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);
    }
}
4

1 回答 1

2

我想说不可能使用gethostbyname().


另外:gethostbyname()已过时,请getnameinfo()改用。

于 2012-04-18T17:04:33.510 回答