و اما نوبت به اجرای کد TCP میرسد. باتوجهبه پیکربندی نرمافزار میکروکنترلر و به جهت سادگی (چون پیغام اول را کلاینت میفرستد)، حالت TCP Server را در میکرو پیادهسازی میکنیم. کلاینت (PC) یک ارتباط رو در پورت موردنظر رو باز میکنه (open)؛ تعدادی داده رو ارسال (TCP send) و سعی میکنه به همون تعداد داده بخونه و بعد ارتباط رو میبنده (close). برای اجرای این کد در محیط LabVIEW قطعه کد زیر را استفاده کردهایم:

در میکروکنترلر به درخواست ارتباط جواب مثبت میدیم و دادههای ارسالی از طرف کامپیوتر رو به خودش برمیگردونیم (echo). اولین پیام دریافتی؛ اولین سگمنت از هندشیک شروع خواهد بود. کامپیوتر بهعنوان کلاینت، درخواستی برای شروع ارتباط به میکروکنترلر ارسال میکنه، بالطبع اولین قدم اینه که در تابع IP_Process بررسی کنیم که آیا پکت فعلی (در پروتکل IP) یک پکت شامل سگمنت TCP هست یا نه؟ کد تابع IP_Process بهصورت زیر تغییر میکنه:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
if (ipFrame->protocol == IP_FRAME_PROTOCOL_ICMP) //==0x01 { newDataLen = ICMP_Process((ICMP_EchoFrame*)ipFrame->data, dataLen); } else if (ipFrame->protocol == IP_FRAME_PROTOCOL_UDP) // ==0x11 { newDataLen = UDP_Process((UDP_Frame*)ipFrame->data, dataLen); } else if (ipFrame->protocol == IP_FRAME_PROTOCOL_TCP) // ==0x06 { newDataLen = TCP_Process((TCP_Frame*)ipFrame->data, dataLen,ipFrame); } |
گام بعدی، تعریف ثوابتی مثل شماره پورت و بیتهای بخش flags است؛
آفست Seq num رو هم مقدار ثابت 0x1A در نظر گرفتیم؛ هرچند بهتره این مقدار تصادفی انتخاب بشه. در بعضی مراجع مقدار آفست رو init seq num هم گفتهاند. همچنین ساختاری برای پردازش هدر TCP تعریف میکنیم و یک define برای بهدستآوردن طول قسمت Options در صورت وجود.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#define TCP_DEMO_PORT 2020 #define TCP_MYSEQ 0x1A #define OPTION_LENGTH(x) ( ( (x >> 12) & 0x000f) * 4 - 20 ) #define TCP_FIN_FLAG (1<<0) #define TCP_SYN_FLAG (1<<1) #define TCP_RST_FLAG (1<<2) #define TCP_PSH_FLAG (1<<3) #define TCP_ACK_FLAG (1<<4) #define TCP_URG_FLAG (1<<5) //tcp header length 20~60 (option 0~40)bytes typedef struct TCP_Frame { uint16_t srcPort; uint16_t destPort; uint32_t seqnum; uint32_t acknum; uint16_t flags; uint16_t winsize; uint16_t chksum; uint16_t urgptr; uint8_t data[]; // options+data } TCP_Frame; |
مطابق روالمون تا اینجا، تابعی بنام TCP_Process مینویسیم که کدهای این پروتکل رو اجرا کنه.
در این تابع؛ ابتدا دو مورد رو بررسی میکنیم. آیا پیغام، روی پورت مدنظر ما ارسال شده است؟ و آیا چک سام صحیح است؟
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
if ( (ntohs(tcpFrame->destPort)) == TCP_DEMO_PORT) { uint16_t calcCheckSum = TCP_CalcCheckSum (( uint8_t* ) tcpFrame, frameLen ) ; if ( rxCheckSum == calcCheckSum ) { } } |
اگر این موارد صحیح باشد، وارد قسمت اصلی پردازش میشویم. بخش Flags رو در یک متغیر ذخیره میکنیم:
flag = htons(tcpFrame->flags);
پکت های دریافتی سه حالت خواهند داشت:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
if( flag & TCP_SYN_FLAG)//it is SYN packet => create SYNACK packet { temp=0x0000; tcpFrame->flags = htons((temp | TCP_ACK_FLAG | TCP_SYN_FLAG | (((uint16_t)6)<<12))); myack=(ntohl(tcpFrame->seqnum)) +1; tcpFrame->acknum= htonl(myack); tcpFrame->seqnum = htonl(TCP_MYSEQ); myseq=TCP_MYSEQ+1; tcpFrame->winsize = htons(8192); tcpFrame->urgptr = 0; //only MSS Option(0x02) . for this example MSS=1460=0x05B4 tcpFrame->data[0]=0x02; tcpFrame->data[1]=0x04; tcpFrame->data[2]=0x05; tcpFrame->data[3]=0xB4; newFrameLen = 24; } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
else if(flag & TCP_PSH_FLAG) { temp=0x0000; tcpFrame->flags = htons((temp | TCP_ACK_FLAG | TCP_PSH_FLAG | (((uint16_t)5)<<12))); myack=(ntohl(tcpFrame->seqnum)) +(frameLen-20); tcpFrame->acknum= htonl(myack); tcpFrame->seqnum = htonl(myseq); myseq+=(frameLen-20); tcpFrame->winsize = htons(8192); newFrameLen = frameLen; } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
else if(flag & TCP_FIN_FLAG) { temp=0x0000; tcpFrame->flags = htons((temp | TCP_ACK_FLAG | TCP_FIN_FLAG | TCP_RST_FLAG | (((uint16_t)5)<<12))); myack=(ntohl(tcpFrame->seqnum)) +(frameLen-20); tcpFrame->acknum= htonl(myack); tcpFrame->seqnum = htonl(myseq); myseq+=(frameLen-20); newFrameLen = frameLen; } |
در اینجا به پایان این نوشتار رسیدیم؛ اگر وقتی باشه و حوصلهای؛ احتمالاً پروتکل HTTP هم به متن اضافه خواهد شد. اما اگر شما تونستید تا اینجا خودتون رو برسونید؛ بهراحتی میتونید پروتکلهای دیگه رو هم خودتون اجرا کنید. در ادامه به ضمیمهها خواهیم پرداخت و در بخش نهایی نیز تمامی کدها قرار داده خواهند شد. موفق باشید.
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.