데이터통신 시간에 나온 과제입니다.

사용자에게서 문자열을 받아 Checksum을 구해 이를 마지막에 붙인 후 보냅니다.

보내는 중간에 bit당 독립적으로 0.1%의 확률로 에러가 발생합니다.

Receiver는 Checksum을 확인하여 에러를 발견하면

에러를 발견했다는 메시지와 Sender에게 재전송을 요청합니다.

만약 에러가 없음이 확인되었다면 해당 메시지를 출력합니다.

리눅스에서 작동하도록 하고 언어는 C언어입니다.

 

0.1%라는 확률을 구하기 위해 저는 이렇게 생각했습니다.

'난수를 0~999까지 나오게 한 후 내가 500이라는 숫자를 정했다고 하자.

그럼 0~999 중 500이 나올 확률은 0.1%일 것이다.

따라서 난수가 500이 되면 에러를 발생시키고, 아니면 에러가 없다고 하자.'

 

하지만 교수님께서 수업 시간에 [0, 1) 사이의 난수를 발생시키는 함수를 사용하여

0.001보다 작은 값이 나오면 0.1%이라는 확률이 만들어집니다.

생각해보니 이것이 좀 더 명확하고 속도도 더 빠르다고 생각합니다.

그래서 처음의 코드를 수정하였습니다.

 

 

#define MAX_SIZE 100 // message size
//#define BIT_ERROR_NUMBER 500 // a number in 0~999. rand return number and compare this number. If they are same, it occur bit error. old code. I changed the code at 2008.05.15.

#include <stdio.h> // include standard input output header
#include <string.h> // include string header
#include <stdlib.h> // include standard library header
#include <time.h> // include time header

/*function declaration*/
unsigned long calculate_checksum(const unsigned char* message, const unsigned long init_checksum); // calculate checksum. retrun checksum.
int sender_site(const unsigned char* ori_message, unsigned char* ret_message); // implement the sender site
void error_in_medium(unsigned char* message, int message_length); // implement medium. It makes 0.1 bit error.
int receiver_site(const unsigned char* received_message, int received_message_length); // implement the receiver site. check the checksum in received message and return a information about error detection.

/*
* main function
* This is main function.
*
* loop the code.
* first, get the message from user.
* second, sender_site make message with checksum.
* third, medium error 0.1% bit independent.
* forth, receiver_site get the message,
*  if checksum is 0, go to first.
*  if checksum is not 0, go to second.
*  but sender_site make the message already. Therefore just resend. It means go to third.
*
*  I clean the input stream to use this code.
*  while(getchar() != '\n')
*  ;
*  This code is introduced at http://couple.haruschool.com/tc/22
*
*
*  return : retrun the value to OS.
*  argument : void
*
*
*  2008.05.11. Bak Jin Yeong.
*
*  First time, I send message alone.
*  but that occurs problem.
*  If checksum is 0 or 01, 02, ... receiver can't know what it is checksum.
*  Because end of the string is 0.
*  Therefore I send message with length.
*
*  2008.05.15. Bak Jin Yeong.
* */
int main(void)
{
    unsigned char user_input_message[MAX_SIZE]; // save the user message
    unsigned char sender_make_message[MAX_SIZE]; // sender make the message with checksum. this message go to receiver site.
    int message_length = 0; // It is number that sender make the message with checksum's length.

    printf("Data Communication Homework - Checksum\n"
            "School ID : 2004314081\n"
            "Name : Bak Jin Yeong\n"); // print my school ID and name.

    while(1) // infinite loop. user don't want to continue, then stop.
    {
        printf("\nInput the message to send : "); // print the message for user writing the message.
        fgets(user_input_message, MAX_SIZE, stdin); // get the message from user.
        if(1 == strlen(user_input_message)) // no message but enter(newline) then, back to first while code.
        {
            continue; // back to printf("\nInput the message to send : ");
        }
        user_input_message[strlen(user_input_message)-1] = 0; // remove new line character(\n)
        message_length = sender_site(user_input_message, sender_make_message); // make the message to send to receiver site with checksum. return value is sender_make_message's length

        do // if receiver get wrong message then resend.
        {
            error_in_medium(sender_make_message, message_length); // occur bit error. persentage is 0.1% and bit independent.
        }
        while(receiver_site(sender_make_message, message_length)); // receiver site received message and check. if error then request to resend.

        printf("continue?(y/n) : "); // print message if user want to continue
        if ('n' == getchar())
        {
            break;
        }
        else // this code clean the input stream. site: http://couple.haruschool.com/tc/22
        {
            while(getchar() != '\n')
                ;
        }
    }

    return 0; // return 0 to OS
}

/*
* sender site function
* This function is implemented sender site.
*
* first, get the checksum to call calculate_checksum function.
* second, add the checksum to end of the message.
*
* return : void
* argument
*  - ori_message : user's message. It's constant because this message is not changed this function.
*  - ret_message : return message. it contains checksum.
*
*
* 2008.05.11. Bak Jin Yeong.
*
* add return value
* return : int - It is ret_message's length
*
* 2008.05.15. Bak Jin Yeong.
* */
int sender_site(const unsigned char* user_message, unsigned char* ret_message)
{
    int user_message_length = strlen(user_message); // get the user_message length.
    long checksum = calculate_checksum(user_message, 0); // get the checksum to call calculate_checksum function. sender's initial checksum is 0.

    strcpy(ret_message, user_message); // copy user_message to ret_message.
    ret_message[user_message_length] = (unsigned char)(checksum >> 8); // attach the checksum first byte to ret_message.
    ret_message[user_message_length+1] = (unsigned char)(checksum & 0xff); // attach the checksum second byte to ret_message.
    ret_message[user_message_length+2] = 0; // end of the string.

    return user_message_length + 2; // return ret_message's length
}

/*
* error in medium function.
* This function is maked bit error.
*
* I get the random number from 0 to 999.
* and I set the number BIT_ERROR_NUMBER.
* If two number is same, it's 0.1% probability.
* Therefore I set bit error use XOR operation.
* X^0 = X, X^1 = ~X
*
* return : void
* argument
*  - message : Sender send to receiver this message. So this function ruin this message.
*
*
*  2008.05.11. Bak Jin Yeong.
*
*    add argument message_length.
*    It is message's length.
*
*    use drand48 function.
*    drand48 return random number range from 0 to 1. [0.0, 1.0)
*    So random number is less than 0.001. It's provavility is 0.1%.
*
*    2008.05.15. Bak Jin Yeong.
*  */
void error_in_medium(unsigned char* message, int message_length)
{
    //int message_length = strlen(message); // get the message length. old code.
    int for_loop_i = 0, for_loop_j = 0; // this variable to use in for loop
    unsigned char occur_bit_error = 0; // this variable make the bit error.
    //srand(time(NULL)); // send the seed to random function. old code.
    srand48(time(NULL)); // send the seed to random function.

    for( ; for_loop_i < message_length ; for_loop_i++) // check the byte from message
    {
        for(for_loop_j = 0 ; for_loop_j < 8 ; for_loop_j++) // check one byte.
        {
            //if(BIT_ERROR_NUMBER == (rand() % 1000)) // rand() % 1000 is returned value from 0 to 999. and BIT_ERROR_NUMBER is range from 0 to 999. So the probability if two number same is 0.1%. replace new code at 2008.05.15.
            if(drand48() < 0.001)
            {
                occur_bit_error += 1; // set the error bit
            }

            occur_bit_error = occur_bit_error << 1; // shift the variable because check next bit.
        }

        message[for_loop_i] ^= occur_bit_error; // if occur_bit_error is 0, then message is not changed. But if occur_bit_error is not 0, then message is changed. It means message has error.
    }
}

/*
* receiver site function.
* This function is implemented receiver site.
*
* First, divide message and checksum from received message.
* Second, get the checksum to call calculate_checksum function.
* Third, if checksum is 0, it's not error or can't detect the error. So print the message and return 0.
* if checksum is not 0, it is error in message. So return -1 to request to resend.
*
* return : checksum. if checksum is not 0, return -1.
* argument
*  - received_message : received message through the medium. Maybe the message damaged.
*   It is received message, So it's constant.
*
*
* 2008.05.11. Bak Jin Yeong.
*
* add argument - received_message_length
* It is received_message's length
*
* 2008.05.15. Bak Jin Yeong.
* */
int receiver_site(const unsigned char* received_message, int received_message_length)
{
    unsigned char workspace_message[MAX_SIZE]; // copy the received_message because received_message is constant.
    //int received_message_length = strlen(received_message); // get the received message length. old code.
    unsigned long received_checksum = 0, checksum = 0; // received_checksum is checksum in received_message. checksum is received_message's checksum.

    received_checksum = (unsigned long)received_message[received_message_length-2]; // get the first byte checksum in received_message.
    received_checksum = received_checksum << 8; // shift the left 8. Because I get the second byte.
    received_checksum += (unsigned long)received_message[received_message_length-1]; // get the second byte checksum in received_message.

    strcpy(workspace_message, received_message); // copy received message to workspace_message.
    workspace_message[received_message_length-2] = 0; // cut the checksum in workspace_message. Then workspace_message have just message string.

    checksum = calculate_checksum(workspace_message, received_checksum); // get the checksum to call the calculate_checksum function.

    if(!checksum) // if checksum is 0
    {
        printf("No Error!!\nThe message is \"%s\"\n\n", workspace_message); // print the message
        return 0; // return 0. Then main function doesn't request to resend.
    }
    else // if checksum is not 0
    {
        printf("Error Detection!! \nSo I request the retransmission to sender.\n\n"); // print the status.
        return -1; // return -1. The main function request to resend.
    }
}

/*
* calculate checksum function.
* This function calculate the message's checksum and return.
*
* checksum is 16bit(2byts). So I divied message as two bytes.
* But This checksum is one's complement arithmetic. If carry is appear, add it.
* So I use long(4 byte) to save the carry. When all add operation is finished, add upper 2 byte and lower 2 byte.
*
* return : checksum. It's long data type. but use lower 2 bytes.
* argument
*  - message : this function make the checksum to this message.
*  - init_checksum : It's 0 in sender site, and received checksum in receiver site.
*
*
*  2008.05.11. Bak Jin Yeong.
* */
unsigned long calculate_checksum(const unsigned char* message, const unsigned long init_checksum)
{
    int string_length = strlen(message); // get the message length
    int while_loop_i = 0; // this variable use in while loop.
    unsigned long operand_next = 0; // next operand 2 byte.
    unsigned long checksum = 0; // checksum.

    // do while loop. It execute message's length / 2 times.
    // If message's length is 8 byte, initial variable checksum(not init_checksum) is 0. So add 4 times.
    do
    {
        operand_next = (unsigned long)message[while_loop_i]; // get the message's first byte
        operand_next = operand_next << 8; // shift left 8. Because it's upper byte.
        operand_next += (long)message[while_loop_i+1]; // get the message's second byte

        checksum += operand_next; // add two 2bytes.

        while_loop_i += 2; // add 2 because of next two bytes is executed.

    }
    while(while_loop_i < string_length); // It execute message's length / 2 times.

    checksum += init_checksum; // add sum and init_checksum

    checksum = checksum + (checksum >> 16); // add upper two bytes and lower two bytes.
    checksum = ~checksum; // complement
    checksum &= 0x0000ffff; // clean the upper 2 bytes.

    return checksum; // return checksum
}

크리에이티브 커먼즈 라이선스
Creative Commons License

글에 잘못된 점, 다른 점, 부족한 점이 있다면 지적해주세요.
댓글, 트랙백, 메일 모두 고맙습니다.

트랙백 주소 :: http://nosyu.pe.kr/trackback/1547

댓글을 달아 주세요

[로그인][오픈아이디란?]