×

Loading...
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务

Thanks for all the replies. The program simulates a layer 2 communication, neither TCP nor UDP. It is on Linux. I attached the source codes here.

本文发表在 rolia.net 枫下论坛(1)main.c


#include "assign1.h"

int sTOr[2], rTOs[2];
pid_t receiverPID;

int main(int argc, char *argv[]) {
if (argc != 2) {
printf("ass1 <filename>\n");
exit(1);
}

if (pipe(sTOr) || pipe(rTOs)) {
perror("main(): pipe: ");
exit(errno);
}

if ((receiverPID = fork()) < 0) {
perror("main(): fork: ");
exit(errno);
}
else if (receiverPID == 0) {
if (dup2(sTOr[0], fileno(stdin)) == -1 || dup2(rTOs[1], fileno(stdout)) == -1) {
perror("main(): dup2: ");
exit(errno);
}


close(sTOr[0]);
close(sTOr[1]);
close(rTOs[0]);
close(rTOs[1]);
receiver();
}

close(sTOr[0]);
close(rTOs[1]);
sender(argv[1]);

return 0;
}

short makeChecksum(char *str) {
int x = 0;
short sum = 0;

for (x = 0; x < 128; x++) {
sum += str[x];
}
return (sum%255);
}

(2)sender.c

#include "assign1.h"
#include "sender.h"

extern int sTOr[2];
extern int rTOs[2];

FILE *fp;
static FRAME sendFrame;

void catch_alarm (int sig)
{
printf("Test alarm!");
}

void sender(char filename[]) {
short blockNum = 0;
char reply[5];

sigignore(SIGINT);

sendFrame.SOH = 00000001;
sendFrame.blockNum=0;

if ((fp = fopen(filename, "r")) == NULL) {
perror("receiver(): fopen: ");
exit(errno);
}
while ((readFile(sendFrame.msg)) > 0) {
++sendFrame.blockNum;
sendFrame.blockNumComp = ~sendFrame.blockNum;
sendFrame.checksum = makeChecksum(sendFrame.msg);

printf("\nSENDER: blockNum = %d blockNumComp = %d checksum = %d\n", sendFrame.block
Num,
sendFrame.blockNumComp, sendFrame.checksum);
write(sTOr[1], &sendFrame, sizeof(FRAME));
signal(SIGALRM, catch_alarm);
alarm(1);
while(1) {
read(rTOs[0], reply, sizeof("ACK"));
printf("%s was received\n", reply);

if (!strcmp(reply, "NAK")) {
printf("SENDER2: blockNum = %d blockNumComp = %d checksum = %d\n",
sendFrame.blockNum,
sendFrame.blockNumComp, sendFrame.checksum);
write(sTOr[1], &sendFrame, sizeof(FRAME));
}
else if (!strcmp(reply, "ACK"))
break;
else
exit(12);
}
}
}

int readFile(char *str) {
int x;

for(x = 0; x < 128; x++)
str[x] = '\0';
return fread(str, sizeof(char), 128, fp);
}

(3)receiver.c
#include "assign1.h"
#include "receiver.h"

FRAME rFrame;

void receiver() {

sigset(SIGINT, makeError);

while (1) {
if (read(STDIN_FILENO, &rFrame, sizeof(FRAME)) > 0) {
sleep(1);

fprintf(stderr, "RECEIVER: blockNum = %d blockNumComp = %d checksum = %d\n
msg = %s\n", rFrame.blockNum,
rFrame.blockNumComp, rFrame.checksum, rFrame.msg);
if (!checkSOH(rFrame.SOH) ||
!checkBlockNum(rFrame.blockNum, rFrame.blockNumComp) ||
!checkChecksum(rFrame.msg, rFrame.checksum))
write(STDOUT_FILENO, "NAK", sizeof("NAK"));
/* printf("Test!!!"); */
else
write(STDOUT_FILENO, "ACK", sizeof("ACK"));
}
}
}

int checkSOH(char SOH){
return (SOH == 00000001);
}

int checkBlockNum(const short blockNum, const short blockNumComp) {
short newComp = ~blockNum;

if (newComp == blockNumComp)
return 1; // No error

return 0; // Error
}

int checkChecksum(char *str, const short checksum) {
if (makeChecksum(str) == checksum)
return 1; // No error

return 0; // Error
}

void makeError() {
int n = rand()%3;
switch (n) {
case 0:
rFrame.blockNum = 0;
fputs("\nCHANGED BLOCK NUMBER\n", stderr);
break;
case 1:
rFrame.checksum = 0;
fputs("\nCHANGED CHECKSUM\n", stderr);
break;
case 2:
rFrame.blockNumComp = 10;
fputs("\nCHANGED BLOCK NUMBER COMPLIEMENT\n", stderr);
break;
}
}更多精彩文章及讨论,请光临枫下论坛 rolia.net
Report

Replies, comments and Discussions:

  • 工作学习 / 学科技术讨论 / Need help for a small C program
    本文发表在 rolia.net 枫下论坛I'm taking a networking course. One assignment is about modifying an existing C program to handle network communication differently. It might be a breeze for all C programmers. But for me, who learned C language almost 18 years ago and have never done any C programming since then, it is a big challenge. Could someone give me a hand?

    The existing program simulates the communication between two machines over the network. There is a sender program which sends data and waits for response from the receiver, and then decides whether to continue sending next unit of data or resend the last unit based on the response it receives from the receiver. This continues until all data is transmitted.

    The assignment is to introduce a SIGALRM function in the sender program and set the timer to 2 seconds. If the sender gets a response within two seconds from the receiver, turn off the alarm and transmit the next unit of data. If no response is received, time out function kicks in and retransmits the last unit of data.

    I have no idea about how to use SIGALRM function and how to set timer. I tried to google it out but still don't get it. Any help is greatly appreciated.更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • Normally the receive function ( recv() or something like that) has a parameter to indicator the timer. You can check the return value of the function to determine it is timed out or not.
    • Google SIGALRM. Use alarm() to start a timer. Use signal() to install a function to run when SIGALRM is received.
    • believe you need introduce multi-thread
      my opinion:
      get a timer thread and the existing sender/receiver thread
      set a mutual parameter accessible for both threads indicating the receiving status
      everytime after sending a packet, start timer thread, timer thread sleeps for 2 sec
      after sleeping, check the receiving status parameter
      in sender/receiver thread, after sending a packet, open socket waiting for response, if got any, set parameter to received status, kill time thread, send next
    • Using TCP/IP socket or not? On Unix & linux? SIGALRM is for posix threads?
    • 既然是作业, 应该交代用TCP还是UDP. TCP简单些, 连起来听两分钟就行了. 我个人猜测, 恐怕是让你们用UDP, 发i am alive, are you alive之类的信号. timer一定要multithreaded.
      • Thanks for all the replies. The program simulates a layer 2 communication, neither TCP nor UDP. It is on Linux. I attached the source codes here.
        本文发表在 rolia.net 枫下论坛(1)main.c


        #include "assign1.h"

        int sTOr[2], rTOs[2];
        pid_t receiverPID;

        int main(int argc, char *argv[]) {
        if (argc != 2) {
        printf("ass1 <filename>\n");
        exit(1);
        }

        if (pipe(sTOr) || pipe(rTOs)) {
        perror("main(): pipe: ");
        exit(errno);
        }

        if ((receiverPID = fork()) < 0) {
        perror("main(): fork: ");
        exit(errno);
        }
        else if (receiverPID == 0) {
        if (dup2(sTOr[0], fileno(stdin)) == -1 || dup2(rTOs[1], fileno(stdout)) == -1) {
        perror("main(): dup2: ");
        exit(errno);
        }


        close(sTOr[0]);
        close(sTOr[1]);
        close(rTOs[0]);
        close(rTOs[1]);
        receiver();
        }

        close(sTOr[0]);
        close(rTOs[1]);
        sender(argv[1]);

        return 0;
        }

        short makeChecksum(char *str) {
        int x = 0;
        short sum = 0;

        for (x = 0; x < 128; x++) {
        sum += str[x];
        }
        return (sum%255);
        }

        (2)sender.c

        #include "assign1.h"
        #include "sender.h"

        extern int sTOr[2];
        extern int rTOs[2];

        FILE *fp;
        static FRAME sendFrame;

        void catch_alarm (int sig)
        {
        printf("Test alarm!");
        }

        void sender(char filename[]) {
        short blockNum = 0;
        char reply[5];

        sigignore(SIGINT);

        sendFrame.SOH = 00000001;
        sendFrame.blockNum=0;

        if ((fp = fopen(filename, "r")) == NULL) {
        perror("receiver(): fopen: ");
        exit(errno);
        }
        while ((readFile(sendFrame.msg)) > 0) {
        ++sendFrame.blockNum;
        sendFrame.blockNumComp = ~sendFrame.blockNum;
        sendFrame.checksum = makeChecksum(sendFrame.msg);

        printf("\nSENDER: blockNum = %d blockNumComp = %d checksum = %d\n", sendFrame.block
        Num,
        sendFrame.blockNumComp, sendFrame.checksum);
        write(sTOr[1], &sendFrame, sizeof(FRAME));
        signal(SIGALRM, catch_alarm);
        alarm(1);
        while(1) {
        read(rTOs[0], reply, sizeof("ACK"));
        printf("%s was received\n", reply);

        if (!strcmp(reply, "NAK")) {
        printf("SENDER2: blockNum = %d blockNumComp = %d checksum = %d\n",
        sendFrame.blockNum,
        sendFrame.blockNumComp, sendFrame.checksum);
        write(sTOr[1], &sendFrame, sizeof(FRAME));
        }
        else if (!strcmp(reply, "ACK"))
        break;
        else
        exit(12);
        }
        }
        }

        int readFile(char *str) {
        int x;

        for(x = 0; x < 128; x++)
        str[x] = '\0';
        return fread(str, sizeof(char), 128, fp);
        }

        (3)receiver.c
        #include "assign1.h"
        #include "receiver.h"

        FRAME rFrame;

        void receiver() {

        sigset(SIGINT, makeError);

        while (1) {
        if (read(STDIN_FILENO, &rFrame, sizeof(FRAME)) > 0) {
        sleep(1);

        fprintf(stderr, "RECEIVER: blockNum = %d blockNumComp = %d checksum = %d\n
        msg = %s\n", rFrame.blockNum,
        rFrame.blockNumComp, rFrame.checksum, rFrame.msg);
        if (!checkSOH(rFrame.SOH) ||
        !checkBlockNum(rFrame.blockNum, rFrame.blockNumComp) ||
        !checkChecksum(rFrame.msg, rFrame.checksum))
        write(STDOUT_FILENO, "NAK", sizeof("NAK"));
        /* printf("Test!!!"); */
        else
        write(STDOUT_FILENO, "ACK", sizeof("ACK"));
        }
        }
        }

        int checkSOH(char SOH){
        return (SOH == 00000001);
        }

        int checkBlockNum(const short blockNum, const short blockNumComp) {
        short newComp = ~blockNum;

        if (newComp == blockNumComp)
        return 1; // No error

        return 0; // Error
        }

        int checkChecksum(char *str, const short checksum) {
        if (makeChecksum(str) == checksum)
        return 1; // No error

        return 0; // Error
        }

        void makeError() {
        int n = rand()%3;
        switch (n) {
        case 0:
        rFrame.blockNum = 0;
        fputs("\nCHANGED BLOCK NUMBER\n", stderr);
        break;
        case 1:
        rFrame.checksum = 0;
        fputs("\nCHANGED CHECKSUM\n", stderr);
        break;
        case 2:
        rFrame.blockNumComp = 10;
        fputs("\nCHANGED BLOCK NUMBER COMPLIEMENT\n", stderr);
        break;
        }
        }更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • Ask your TA/Prof, they will provide help, ask somewhere else does not really help you as much as they do.
      • Thanks for the suggestion. TA and prof won't help me in writing the code. I don't have any problem understanding the networking theory. I just don't have time to pick up C programming from beginning.