데이터통신 시간에 나온 과제입니다.
사용자에게서 문자열을 받아 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
}
- 2008년 2학기 컴퓨터공학실습2 - Exercise 01_02 (0)2008/09/16
- 2008년 2학기 컴퓨터공학실습2 - Exercise 01_01 (0)2008/09/16
- 2008년 1학기 기호논리학 - 양화논리 (6)2008/07/07
- 2008년 1학기 데이터통신 - Checksum (0)2008/06/21
- 2008년 1학기 공학컴퓨터프로그래밍 - MATLAB why... (0)2008/06/21
- 2008년 1학기 공학수학1 - Stability Criteria fo... (0)2008/06/21
- 2008년 1학기 시스템 프로그래밍 - Embedding Ass... (4)2008/06/09
글에 잘못된 점, 다른 점, 부족한 점이 있다면 지적해주세요.
댓글, 트랙백, 메일 모두 고맙습니다.







댓글을 달아 주세요