UNIX停止和等待协议中的分段错误

时间:2013-03-13 21:02:46

标签: c unix segmentation-fault

您好我正在UNIX中编写一个C程序来模拟套接字停止&等待学校协议。当我在命令行输入4个参数时,我不断收到分段错误。如果我输入多于或少于4然后我得到正确的错误抛出。如果有人可以提供帮助,将不胜感激。提前谢谢。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <strings.h>

#define SERVER_PORT 6500
#define MAX_LINE 256

int
main(int argc, char * argv[])
{
        FILE *fp;
        struct hostent *hp;
        struct sockaddr_in sin, client;
        char *host;
        char ack[MAX_LINE], buf[MAX_LINE], fname[MAX_LINE];
        int s, i, rnum, drop;
        int8_t current, last = -1;
        int rval, slen, NFrames, len;

        long LenFile;
        struct timeval rectime;  //The struct timeval structure represents an elapsed time
        struct timeval zone;

        if (argc==4){
                host=argv[1];
        }
        else {
            fprintf(stderr, "usage: simplex-talk host\n");
             //fprintf(stderr, "hello");
                exit(1);
        }

        if (!hp) {
                fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
                exit(1);
        }

        bzero((char *)&sin, sizeof(sin));
        sin.sin_family = AF_INET;
        bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
        sin.sin_port=htons(SERVER_PORT);

        if((s=socket(PF_INET, SOCK_DGRAM,0)) < 0){
                 perror("simplex-talk; socket");
                 exit(1);
        }

        // create file request
        sprintf(buf, "%s\0", argv[3]);

        if ((rval=sendto(s,buf,sizeof(buf),0,(struct sockaddr *)&client,sizeof(client)))< 0) {
printf("sjkdfj");
perror("writing on datagram socket");
        }
        system("date");
        printf("Sent request for file %s at time = %ld %ld\n", argv[3], rectime.tv_sec, rectime.tv_usec);

        bzero(ack,sizeof(ack));
        slen = sizeof(client);

    buf[MAX_LINE-1] = '\0';
    len = strlen(buf) + 1;
         //request to send, waiting....

        while ((rval = recvfrom(s,ack,sizeof(ack),0,(struct sockaddr *)&client,&slen))<0){
                perror("receiver recvfrom");
                printf(stderr, "hhhhhhhh");
}
          //get time
        if (gettimeofday(&rectime, &zone) < 0) {
                perror("getting time");
                exit(1);
        }
        if(ack[0] == '0'){
                printf("Received file not found, time = %ld %ld, File = \"%s\"\n", rectime.tv_sec, rectime.tv_usec, fname);
        }
        if(ack[0] == '1') {
                char ch[MAX_LINE];
                int i, j;
                for(i=2, j=0; ack[i] != ' '; i++, j++){
                        ch[j] = ack[i];
                }
                ch[i++] = '\0';
                LenFile=atoi(ch);
                for(j=0; ack[i] && ack[i] != '.'; i++, j++){
                        fname[j] = ack[i];
                }
                fname[i++] = '\0';
                strcat(fname, "client.txt");
                NFrames = LenFile / MAX_LINE + (LenFile % MAX_LINE == 0 ? 0:1);
                printf("Received, ack sent, time = %ld %ld\nfname = \"%s\"\n", LenFile = "%d\n", rectime.tv_sec, rectime.tv_usec, fname, LenFile);

                //file I/O (reads)
                fp=fopen(fname, "w");
                if(fp==NULL){
                        perror("Opening File for Writing");
                        exit(1);
                }
                printf("Opening File %s for writing\n", fname);
                drop = 0;

                for(i=0; i < NFrames; ){
                        bzero(ack,sizeof(ack));
                        while ((rval = recvfrom(s,ack,sizeof(ack),0,(struct sockaddr *)&client,&slen))<0){
                                perror("receiver recvfrom");
                        }
 //get time
                        if (gettimeofday(&rectime, &zone) < 0) {
                                perror("getting time");
                                exit(1);
                        }
                        current = ack[0];
                        if(current == last) {
                                printf("Duplicate frame %d received\n", last);
                                continue;
                        }
                        printf("Recieved Frame #%d at time = %ld %ld\n\nContent:\n%s\n", current, rectime.tv_sec, rectime.tv_usec, ack+1);
                        fputs(ack+1, fp);

                        //creating ack
                        bzero(buf,sizeof(buf));
                        sprintf(buf, "%c%s\0", current, "ackp");

                        //25% chance of loss is to call random()
                        rnum = random();
                        if((rnum%4) != 0) {
                                // get time
                                if (gettimeofday(&rectime, &zone) < 0) {
                                        perror("getting time");
                                        exit(1);
                                }
                                if ((rval=sendto(s,buf,sizeof(buf),0,(struct sockaddr *)&client,sizeof(client))) < 0) {
                                perror("writing on datagram socket");
                                }else{
                                        i++;
                                        last = current;
                                        printf("Sent Received Packet ACK for Frame %d at time = %ld %ld\n", current, rectime.tv_sec, rectime.tv_usec);
                                }
                        }else{
                                drop++;
                        }
                }
                 printf("Total Number of dropped frames is %d\n", drop);
                //get time
                if (gettimeofday(&rectime, &zone) < 0) {
                        perror("getting time");
                        exit(1);
                }
                fclose(fp);
                printf("Closing file for writing at time = %ld %ld\n", rectime.tv_sec, rectime.tv_usec);
        }
        //get time
        if (gettimeofday(&rectime, &zone) < 0) {
                perror("getting time");
                exit(1);
        }
        printf("Closing Socked %d for File \"%s at time = %ld %ld\n", ntohs(client.sin_port), fname, rectime.tv_sec, rectime.tv_usec);
        close(s);
}

2 个答案:

答案 0 :(得分:0)

需要注意的一点是:argc包含传递给程序的参数计数+一个用于程序名称的参数计数。因此,如果您使用4个参数运行程序,则无法满足argc = 5if (argc==4)。如果这不能解决问题,那么segfault的堆栈是什么?

答案 1 :(得分:0)

您的第一个问题出在此处:

bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);

hp指向哪里?这是一个你没有初始化的指针,它指向内存中的一些随机区域。访问不属于您的内存中的某些随机区域是不好的。不要这样做。