c语言 - UNIX 停止和等待协议中的分段错误



嗨,我目前正在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 hostn");
             //fprintf(stderr, "hello");
                exit(1);
        }
        if (!hp) {
                fprintf(stderr, "simplex-talk: unknown host: %sn", 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", 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 %ldn", argv[3], rectime.tv_sec, rectime.tv_usec);
        bzero(ack,sizeof(ack));
        slen = sizeof(client);
    buf[MAX_LINE-1] = '';
    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++] = '';
                LenFile=atoi(ch);
                for(j=0; ack[i] && ack[i] != '.'; i++, j++){
                        fname[j] = ack[i];
                }
                fname[i++] = '';
                strcat(fname, "client.txt");
                NFrames = LenFile / MAX_LINE + (LenFile % MAX_LINE == 0 ? 0:1);
                printf("Received, ack sent, time = %ld %ldnfname = "%s"n", LenFile = "%dn", 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 writingn", 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 receivedn", last);
                                continue;
                        }
                        printf("Recieved Frame #%d at time = %ld %ldnnContent:n%sn", current, rectime.tv_sec, rectime.tv_usec, ack+1);
                        fputs(ack+1, fp);
                        //creating ack
                        bzero(buf,sizeof(buf));
                        sprintf(buf, "%c%s", 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 %ldn", current, rectime.tv_sec, rectime.tv_usec);
                                }
                        }else{
                                drop++;
                        }
                }
                 printf("Total Number of dropped frames is %dn", drop);
                //get time
                if (gettimeofday(&rectime, &zone) < 0) {
                        perror("getting time");
                        exit(1);
                }
                fclose(fp);
                printf("Closing file for writing at time = %ld %ldn", 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 %ldn", ntohs(client.sin_port), fname, rectime.tv_sec, rectime.tv_usec);
        close(s);
}

你的第一个问题在这里:

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

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

有一点需要注意:argc包含传递给程序的参数计数+一个程序名称。因此,如果您运行带有4个参数的程序,那么argc = 5if (argc==4)将不满足。如果这不能解决问题,分段错误的堆栈是什么?

最新更新