الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

تابع برمجة الشبكات : الجزء الثالث

مغلق
بدأه HGB في 20 مارس 2005 · 5 رد · 2,927 مشاهدة · في قسم المواضيع الهامة في قسم السي /سي++
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ,

في المستوى السابق هنا :

/index.php?showtopic=37152

تحدثنا عن العديد من التقنيات في برمجة الشبكات بإستخدام winsock تحديدا , وهنا سنتابع المزيد وشيئا فشيئا بإذن الله .

وهنا أيضا تم التحدث عن تقنية Blocking و Non-Blocking Sockets ,

/index.php?showtopic=59345

الحقيقة أنني أكتب برنامج بإستخدام winsock حاليا وأحببت أن أضيف بعض ماأستفيد منه وألخصه للجميع لتعم الفائدة , لذا ربما يكون الكلام غير متناغم تماما , ففي الجزء الأول بدأنا جلسات للتعلم مباشرة لكن حاليا أضيف بعض الملخصات وإن كان هذا يعني الحاجة للتفاعل أيضا .

لندخل في صلب الموضوع :

=================================

في الجزء السابق قبل مدة الأخ Perfect Stranger تحدث عن إمكانية إضافة ال IP Header مع الحزمة المرسلة ليمكن إستلامها من الطرف الآخر للإستفادة من معلومات ال IP Header وحتى ال TCP أو UDP HEADER , المهم في الأمر أن هذه العملية يمكن تطبيقها بإستخدام الدالة setsocketopt بالبارمتر IP_HDRINCL كالتالي :

bOpt = TRUE;
    ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));

ففي عند هذه النقطة سنحتاج لأن نحسب حسابات ال ip header والذي يليه سواء TCP أم UDP أو حتى ICMP بالطريقة التي نحددها نحن , لكي نغير في معلومات IP Header المرسلة !

الآن هذا عبث حقيقي يمكنك من تغيير عنوان المرسل لو كان من جهازك مثلا بالعنوان 192.168.0.1 فيمكن أن تغيره لأي شيء ليظهر للمستلم كأنه 10.10.10.5 , وأيضا منفذ الإرسال هو غالبا مايستخدم للإستقبال الحزم المردودة من الطرف البعيد .

لتتعرف أكثر على الوضع تحتاج لمعرفة بنية TCP/IP وال udp , "وهي ماسندرسه هنا " وهي كالتالي :

بالنسبة ل IP HEADER :

ip_header.jpg

بالنسبة ل TCP Header :

tcp_header.jpg

وأخيرا UDP Header :

udp_header.jpg

الآن لفهم الوضع خذ هذا المثال ل packet مستلمة وراقب المدخلات وقارنها بالبنية :

ip_header_data.jpg

في البداية نراقب ال IP Header :

أول بايتين وهي الرقم المخزن في الخلية A1 , وهو في هذه الحال 45 , فالرقم 4 يرمز لنسخة بروتوكول IP وهو هنا Ipv4 , ولاحقا في عام 2010 تقريبا سيتم التعامل رسميا ببروتوكول Ipv6 بشكل ققياسي حيث فرقه الرئيسي من Ipv4 هو أن عناوين IP التي يحملها بعرض 128 بت بدل من 32 بت فقط في النسخة الحالية IPv4 .

البايت التالي من 45 وهو الرقم 5 فيرمز لطول IPHeader وهو هنا بالبايتات يعني 5 بايت وهي 5X32 بت = 160 بت .

طول الحزمه وهو موجوده في الخليتين C1 and D1. في هذه الحاله تحملان القيم 00 و C2. 00 تدل على صفر و C2 تدل على 44 بعد تحوبلها من النظام السادس عشري الى النظام العشري .وهذا يدل على ان الحزمه طولها 44 . وبمعرفة IHL وطول الحزمة يمكننا معرفة بدايه الخلايا التي بها ال DATA في الحزمة حيث بدايه الجزء الذي به الDATA = Length-IHL.

الخليه I1 وهي تدل على قيمة المتغير TTL ( Time To Live ) للحزمه والذي ينقص بواحد عند كل موجه Router تمر به الحزمه وعندما تكون قيمة هذا المتغير صفرا فان ذلك يدل على عدم صلاحية الحزمة .

الخلية J1 تدلنا على نوع البروتوكول المستخدم في الحزمة. في هذه الحزمه القيمة هي 06 وهذا يدل على بروتوكول TCP . بالنسبه لدراستنا هذه فاننا معنيون بالحزم من هذا النوع تلك التي تحمل القيمه 06 في الخليه J1. وهذه بعض الامثله على القيم التي يمكن ان تحملها هذه الخليه والبروتوكولات التي تدل عليها :

	1 = ICMP
	2 = IGMP
	6 = TCP
	17 = UDP

الآن فلننتقل لمستوى TCP :

عنوان المرسل ( Source IP Address ) الموجود في الخلايا ( M1,N1,O1 and P1 ) في هذه الحاله فان عنوان المرسل هو 172.16.0.9.

عنوان المستقبل ( Destination IP Address ) الموجود في الخلايا ( A2,B2,C2 and D2 ) في هذه الحاله عنوان المستقبل هو 172.16.0.1.

الخليتين ( G2 and H2 ) تدلان على عنوان منفذ البيانات المستقبل للحزمة. في هذه الحاله هي 00 و 17 بعد التحويل الى عشري هي 23 والتي تدل على Telenet. هنالك عناوين عده تدل على بروتوكولات مستخدمه منها

	12   FTP
	23   Telenet
	25   Mail(SMTP)
	80   HTTP

الخلايا ( M2,N2,O2 and P2 ) تدل على قيمه المتغير ( ACK# ) اي رقم الحزمة التاليه التي ينتظر مرسل الحزمه استقبالها من المستقبل. في هذه الحاله هي 00 00 00 00 وهذه القيمة تدل على ان هذه الحزمه هي حزمة طلب انشاء اتصال بين الجهازين.

الجزء الاول من الخليه A3 والذي يحوي القيمة 06 يدل على طول ال TCP Header والذي يبدا حيث انتهى ال IP Header. اي انه في هذه الحزمه فان الخلايا (A1 to D2) هي المكونه للIP Header والخلايا ( E2 to L3 ) هي للTCP Header.

الجزء الاخير الذي يهمنا من هذه البيانات موجود في الخلايا ( C3 and D3 ) والتي تستخدم لتدل على حجم الWindow للمرسل حسب اسلوب TCP Sliding Window المشروح سابقا.

***

كما رأينا من الشرح السريع فإن إضافة معلومات IP Header يجب أن تكون دقيقة لتحقق النتائج المطلوبة مباشرة , وماعلينا إلا أن نكتبها لتغلف ونرسلها يدويا قبل البيانات التي نريد إرسالها للمستلم البعيد :

إليكم الكود حدقو فيه جيدا وسأتحدث عنه بعد قليل :

[color= #007f00;]#include <winsock2.h>

[color= #007f00;]#include <ws2tcpip.h>

 

[color= #007f00;]#include <stdio.h>

[color= #007f00;]#include <stdlib.h>

 

[color= #007f00;]#define MAX_MESSAGE        4068

[color= #007f00;]#define MAX_PACKET         4096

[color= #007f00;]//

[color= #007f00;]// Set up some default values 

[color= #007f00;]//

[color= #007f00;]#define DEFAULT_PORT       5150

[color= #007f00;]#define DEFAULT_IP         "10.0.0.1"

[color= #007f00;]#define DEFAULT_COUNT      5

[color= #007f00;]#define DEFAULT_MESSAGE    "This is a test"

 

[color= #007f00;]//

[color= #007f00;]// Define the IP header. Make the version and length fields one

[color= #007f00;]// character since we can't declare two 4-bit fields without

[color= #007f00;]// the compiler aligning them on at least a 1-byte boundary.

[color= #007f00;]//

[color= #0000ff;]typedef [color= #0000ff;]struct ip_hdr

[color= #000000;]{

    [color= #0000ff;]unsigned [color= #0000ff;]char  ip_verlen;        [color= #007f00;]// IP version & length

    [color= #0000ff;]unsigned [color= #0000ff;]char  ip_tos;           [color= #007f00;]// IP type of service

    [color= #0000ff;]unsigned [color= #0000ff;]short ip_totallength;   [color= #007f00;]// Total length

    [color= #0000ff;]unsigned [color= #0000ff;]short ip_id;            [color= #007f00;]// Unique identifier 

    [color= #0000ff;]unsigned [color= #0000ff;]short ip_offset;        [color= #007f00;]// Fragment offset field

    [color= #0000ff;]unsigned [color= #0000ff;]char  ip_ttl;           [color= #007f00;]// Time to live

    [color= #0000ff;]unsigned [color= #0000ff;]char  ip_protocol;      [color= #007f00;]// Protocol(TCP, UDP, etc.)

    [color= #0000ff;]unsigned [color= #0000ff;]short ip_checksum;      [color= #007f00;]// IP checksum

    [color= #0000ff;]unsigned [color= #0000ff;]int   ip_srcaddr;       [color= #007f00;]// Source address

    [color= #0000ff;]unsigned [color= #0000ff;]int   ip_destaddr;      [color= #007f00;]// Destination address

[color= #000000;]} IP_HDR, [color= #000000;]*PIP_HDR, FAR[color= #000000;]* LPIP_HDR;

[color= #007f00;]//

[color= #007f00;]// Define the UDP header 

[color= #007f00;]//

[color= #0000ff;]typedef [color= #0000ff;]struct udp_hdr

[color= #000000;]{

    [color= #0000ff;]unsigned [color= #0000ff;]short src_portno;       [color= #007f00;]// Source port number

    [color= #0000ff;]unsigned [color= #0000ff;]short dst_portno;       [color= #007f00;]// Destination port number

    [color= #0000ff;]unsigned [color= #0000ff;]short udp_length;       [color= #007f00;]// UDP packet length

    [color= #0000ff;]unsigned [color= #0000ff;]short udp_checksum;     [color= #007f00;]// UDP checksum (optional)

[color= #000000;]} UDP_HDR, [color= #000000;]*PUDP_HDR;

 

[color= #007f00;]//

[color= #007f00;]// Global variables

[color= #007f00;]//

[color= #0000ff;]unsigned [color= #0000ff;]long  dwToIP,               [color= #007f00;]// IP to send to

               dwFromIP;             [color= #007f00;]// IP to send from (spoof)

[color= #0000ff;]unsigned [color= #0000ff;]short iToPort,              [color= #007f00;]// Port to send to

               iFromPort;            [color= #007f00;]// Port to send from (spoof)

DWORD          dwCount;              [color= #007f00;]// Number of times to send

[color= #0000ff;]char           strMessage[color= #000000;][MAX_MESSAGE[color= #000000;]]; [color= #007f00;]// Message to send

 

 

iToPort [color= #000000;]= DEFAULT_PORT;

    iFromPort [color= #000000;]= DEFAULT_PORT;

    dwToIP [color= #000000;]= inet_addr[color= #000000;](DEFAULT_IP[color= #000000;]);

    dwFromIP [color= #000000;]= inet_addr[color= #000000;](DEFAULT_IP[color= #000000;]); 

    dwCount [color= #000000;]= DEFAULT_COUNT;

    strcpy[color= #000000;](strMessage, DEFAULT_MESSAGE[color= #000000;]);

 

[color= #007f00;]// 

[color= #007f00;]// Function: checksum

[color= #007f00;]//

[color= #007f00;]// Description:

[color= #007f00;]//    This function calculates the 16-bit one's complement sum

[color= #007f00;]//    for the supplied buffer

[color= #007f00;]//

USHORT checksum[color= #000000;](USHORT [color= #000000;]*buffer, [color= #0000ff;]int size[color= #000000;])

[color= #000000;]{

    [color= #0000ff;]unsigned [color= #0000ff;]long cksum[color= #000000;]=[color= #ff0000;]0;

 

    [color= #0000ff;]while [color= #000000;](size [color= #000000;]> [color= #ff0000;]1[color= #000000;])

    [color= #000000;]{

        cksum [color= #000000;]+[color= #000000;]= [color= #000000;]*buffer[color= #000000;]++;

        size  [color= #000000;]-[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](USHORT[color= #000000;]);   

    [color= #000000;]}

    [color= #0000ff;]if [color= #000000;](size[color= #000000;])

    [color= #000000;]{

        cksum [color= #000000;]+[color= #000000;]= [color= #000000;]*[color= #000000;](UCHAR[color= #000000;]*[color= #000000;])buffer;   

    [color= #000000;]}

    cksum [color= #000000;]= [color= #000000;](cksum [color= #000000;]>> [color= #ff0000;]16[color= #000000;]) [color= #000000;]+ [color= #000000;](cksum [color= #000000;]& 0xffff[color= #000000;]);

    cksum [color= #000000;]+[color= #000000;]= [color= #000000;](cksum [color= #000000;]>>[color= #ff0000;]16[color= #000000;]); 

 

    [color= #0000ff;]return [color= #000000;](USHORT[color= #000000;])[color= #000000;](~cksum[color= #000000;]); 

[color= #000000;]}

 

[color= #0000ff;]int main[color= #000000;]([color= #0000ff;]int argc, [color= #0000ff;]char [color= #000000;]**argv[color= #000000;])

[color= #000000;]{

    WSADATA            wsd;

    SOCKET             s;

    [color= #0000ff;]BOOL               bOpt;

    [color= #0000ff;]struct sockaddr_in remote;       [color= #007f00;]// IP addressing structures

    IP_HDR             ipHdr;

    UDP_HDR            udpHdr;

    [color= #0000ff;]int                ret;

    DWORD              i;

    [color= #0000ff;]unsigned [color= #0000ff;]short     iTotalSize,   [color= #007f00;]// Lots of sizes needed to fill

                       iUdpSize,     [color= #007f00;]// the various headers with

                       iUdpChecksumSize,

                       iIPVersion,

                       iIPSize,

                       cksum [color= #000000;]= [color= #ff0000;]0;

    [color= #0000ff;]char               buf[color= #000000;][MAX_PACKET[color= #000000;]],

                      [color= #000000;]*ptr [color= #000000;]= NULL;

    IN_ADDR            addr;

 

    [color= #007f00;]// Parse command line arguments, and print them out

    [color= #007f00;]//

    ValidateArgs[color= #000000;](argc, argv[color= #000000;]);

    addr.[color= #808000;]S_un.[color= #808000;]S_addr [color= #000000;]= dwFromIP;

    printf[color= #000000;]([color= #A31515;]"From IP: <%s>[color= #A31515; font-weight: bold;]n     Port: %d[color= #A31515; font-weight: bold;]n", inet_ntoa[color= #000000;](addr[color= #000000;]),

        iFromPort[color= #000000;]);

    addr.[color= #808000;]S_un.[color= #808000;]S_addr [color= #000000;]= dwToIP;

    printf[color= #000000;]([color= #A31515;]"To   IP: <%s>[color= #A31515; font-weight: bold;]n     Port: %d[color= #A31515; font-weight: bold;]n", inet_ntoa[color= #000000;](addr[color= #000000;]),

        iToPort[color= #000000;]);

    printf[color= #000000;]([color= #A31515;]"Message: [%s][color= #A31515; font-weight: bold;]n", strMessage[color= #000000;]);

    printf[color= #000000;]([color= #A31515;]"Count:   %d[color= #A31515; font-weight: bold;]n", dwCount[color= #000000;]);

 

    [color= #0000ff;]if [color= #000000;](WSAStartup[color= #000000;](MAKEWORD[color= #000000;]([color= #ff0000;]2,[color= #ff0000;]2[color= #000000;]), [color= #000000;]&wsd[color= #000000;]) [color= #000000;]![color= #000000;]= [color= #ff0000;]0[color= #000000;])

    [color= #000000;]{

        printf[color= #000000;]([color= #A31515;]"WSAStartup() failed: %d[color= #A31515; font-weight: bold;]n", GetLastError[color= #000000;]([color= #000000;])[color= #000000;]);

        [color= #0000ff;]return [color= #ff0000;]-1;

    [color= #000000;]}

    [color= #007f00;]//  Creating a raw socket

    [color= #007f00;]//

    s [color= #000000;]= WSASocket[color= #000000;](AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, [color= #ff0000;]0,[color= #ff0000;]0[color= #000000;]);

    [color= #0000ff;]if [color= #000000;](s [color= #000000;]== INVALID_SOCKET[color= #000000;])

    [color= #000000;]{

        printf[color= #000000;]([color= #A31515;]"WSASocket() failed: %d[color= #A31515; font-weight: bold;]n", WSAGetLastError[color= #000000;]([color= #000000;])[color= #000000;]);

        [color= #0000ff;]return [color= #ff0000;]-1;

    [color= #000000;]}

 

    [color= #007f00;]// Enable the IP header include option 

    [color= #007f00;]//

    bOpt [color= #000000;]= TRUE;

    ret [color= #000000;]= setsockopt[color= #000000;](s, IPPROTO_IP, IP_HDRINCL, [color= #000000;]([color= #0000ff;]char [color= #000000;]*[color= #000000;])[color= #000000;]&bOpt, 

       [color= #0000ff;]sizeof[color= #000000;](bOpt[color= #000000;])[color= #000000;]);

    [color= #0000ff;]if [color= #000000;](ret [color= #000000;]== SOCKET_ERROR[color= #000000;])

    [color= #000000;]{

        printf[color= #000000;]([color= #A31515;]"setsockopt(IP_HDRINCL) failed: %d[color= #A31515; font-weight: bold;]n", WSAGetLastError[color= #000000;]([color= #000000;])[color= #000000;]);

        [color= #0000ff;]return [color= #ff0000;]-1;

    [color= #000000;]}

    [color= #007f00;]// Initalize the IP header

    [color= #007f00;]//

    iTotalSize [color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr[color= #000000;]) [color= #000000;]+ [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;]) [color= #000000;]+ strlen[color= #000000;](strMessage[color= #000000;]);

 

    iIPVersion [color= #000000;]= [color= #ff0000;]4;

    iIPSize [color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr[color= #000000;]) [color= #000000;]/ [color= #0000ff;]sizeof[color= #000000;]([color= #0000ff;]unsigned [color= #0000ff;]long[color= #000000;]);

    [color= #007f00;]//

    [color= #007f00;]// IP version goes in the high-order 4 bits of ip_verlen. The

    [color= #007f00;]// IP header length (in 32-bit words) goes in the lower 4 bits.

    [color= #007f00;]//

    ipHdr.[color= #808000;]ip_verlen [color= #000000;]= [color= #000000;](iIPVersion [color= #000000;]<< [color= #ff0000;]4[color= #000000;]) [color= #000000;]| iIPSize;

    ipHdr.[color= #808000;]ip_tos [color= #000000;]= [color= #ff0000;]0;                         [color= #007f00;]// IP type of service

    ipHdr.[color= #808000;]ip_totallength [color= #000000;]= htons[color= #000000;](iTotalSize[color= #000000;]); [color= #007f00;]// Total packet len

    ipHdr.[color= #808000;]ip_id [color= #000000;]= [color= #ff0000;]0;                 [color= #007f00;]// Unique identifier: set to 0

    ipHdr.[color= #808000;]ip_offset [color= #000000;]= [color= #ff0000;]0;             [color= #007f00;]// Fragment offset field

    ipHdr.[color= #808000;]ip_ttl [color= #000000;]= [color= #ff0000;]128;              [color= #007f00;]// Time to live

    ipHdr.[color= #808000;]ip_protocol [color= #000000;]= 0x11;        [color= #007f00;]// Protocol(UDP) 

    ipHdr.[color= #808000;]ip_checksum [color= #000000;]= [color= #ff0000;]0;          [color= #007f00;]// IP checksum

    ipHdr.[color= #808000;]ip_srcaddr [color= #000000;]= dwFromIP;     [color= #007f00;]// Source address

    ipHdr.[color= #808000;]ip_destaddr [color= #000000;]= dwToIP;      [color= #007f00;]// Destination address

    [color= #007f00;]//

    [color= #007f00;]// Initalize the UDP header

    [color= #007f00;]//

    iUdpSize [color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;]) [color= #000000;]+ strlen[color= #000000;](strMessage[color= #000000;]);

 

    udpHdr.[color= #808000;]src_portno [color= #000000;]= htons[color= #000000;](iFromPort[color= #000000;]);

    udpHdr.[color= #808000;]dst_portno [color= #000000;]= htons[color= #000000;](iToPort[color= #000000;]);

    udpHdr.[color= #808000;]udp_length [color= #000000;]= htons[color= #000000;](iUdpSize[color= #000000;]);

    udpHdr.[color= #808000;]udp_checksum [color= #000000;]= [color= #ff0000;]0;

    [color= #007f00;]// 

    [color= #007f00;]// Build the UDP pseudo-header for calculating the UDP checksum.

    [color= #007f00;]// The pseudo-header consists of the 32-bit source IP address, 

    [color= #007f00;]// the 32-bit destination IP address, a zero byte, the 8-bit

    [color= #007f00;]// IP protocol field, the 16-bit UDP length, and the UDP

    [color= #007f00;]// header itself along with its data (padded with a 0 if

    [color= #007f00;]// the data is odd length).

    [color= #007f00;]//

    iUdpChecksumSize [color= #000000;]= [color= #ff0000;]0;

    ptr [color= #000000;]= buf;

    ZeroMemory[color= #000000;](buf, MAX_PACKET[color= #000000;]);

 

    memcpy[color= #000000;](ptr, [color= #000000;]&ipHdr.[color= #808000;]ip_srcaddr,  [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_srcaddr[color= #000000;])[color= #000000;]);  

    ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_srcaddr[color= #000000;]);

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_srcaddr[color= #000000;]);

 

    memcpy[color= #000000;](ptr, [color= #000000;]&ipHdr.[color= #808000;]ip_destaddr, [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_destaddr[color= #000000;])[color= #000000;]); 

    ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_destaddr[color= #000000;]);

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_destaddr[color= #000000;]);

 

    ptr[color= #000000;]++;

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= [color= #ff0000;]1;

 

    memcpy[color= #000000;](ptr, [color= #000000;]&ipHdr.[color= #808000;]ip_protocol, [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_protocol[color= #000000;])[color= #000000;]); 

    ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_protocol[color= #000000;]);

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr.[color= #808000;]ip_protocol[color= #000000;]);

 

    memcpy[color= #000000;](ptr, [color= #000000;]&udpHdr.[color= #808000;]udp_length, [color= #0000ff;]sizeof[color= #000000;](udpHdr.[color= #808000;]udp_length[color= #000000;])[color= #000000;]); 

    ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](udpHdr.[color= #808000;]udp_length[color= #000000;]);

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](udpHdr.[color= #808000;]udp_length[color= #000000;]);

    

    memcpy[color= #000000;](ptr, [color= #000000;]&udpHdr, [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;])[color= #000000;]); 

    ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;]);

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;]);

 

    [color= #0000ff;]for[color= #000000;](i [color= #000000;]= [color= #ff0000;]0; i [color= #000000;]< strlen[color= #000000;](strMessage[color= #000000;]); i[color= #000000;]++, ptr[color= #000000;]++[color= #000000;])

        [color= #000000;]*ptr [color= #000000;]= strMessage[color= #000000;][i[color= #000000;]];

    iUdpChecksumSize [color= #000000;]+[color= #000000;]= strlen[color= #000000;](strMessage[color= #000000;]);

 

    cksum [color= #000000;]= checksum[color= #000000;]([color= #000000;](USHORT [color= #000000;]*[color= #000000;])buf, iUdpChecksumSize[color= #000000;]);

    udpHdr.[color= #808000;]udp_checksum [color= #000000;]= cksum;

    [color= #007f00;]//

    [color= #007f00;]// Now assemble the IP and UDP headers along with the data

    [color= #007f00;]// so we can send it

    [color= #007f00;]//        

    ZeroMemory[color= #000000;](buf, MAX_PACKET[color= #000000;]);

    ptr [color= #000000;]= buf;

 

    memcpy[color= #000000;](ptr, [color= #000000;]&ipHdr, [color= #0000ff;]sizeof[color= #000000;](ipHdr[color= #000000;])[color= #000000;]);   ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](ipHdr[color= #000000;]);

    memcpy[color= #000000;](ptr, [color= #000000;]&udpHdr, [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;])[color= #000000;]); ptr [color= #000000;]+[color= #000000;]= [color= #0000ff;]sizeof[color= #000000;](udpHdr[color= #000000;]);

    memcpy[color= #000000;](ptr, strMessage, strlen[color= #000000;](strMessage[color= #000000;])[color= #000000;]);

 

    [color= #007f00;]// Apparently, this SOCKADDR_IN structure makes no difference.

    [color= #007f00;]// Whatever we put as the destination IP addr in the IP header

    [color= #007f00;]// is what goes. Specifying a different destination in remote

    [color= #007f00;]// will be ignored.

    [color= #007f00;]//

    remote.[color= #808000;]sin_family [color= #000000;]= AF_INET;

    remote.[color= #808000;]sin_port [color= #000000;]= htons[color= #000000;](iToPort[color= #000000;]);

    remote.[color= #808000;]sin_addr.[color= #808000;]s_addr [color= #000000;]= dwToIP;

   

    [color= #0000ff;]for[color= #000000;](i [color= #000000;]= [color= #ff0000;]0; i [color= #000000;]< dwCount; i[color= #000000;]++[color= #000000;])

    [color= #000000;]{

        ret [color= #000000;]= sendto[color= #000000;](s, buf, iTotalSize, [color= #ff0000;]0, [color= #000000;](SOCKADDR [color= #000000;]*[color= #000000;])[color= #000000;]&remote, 

            [color= #0000ff;]sizeof[color= #000000;](remote[color= #000000;])[color= #000000;]);

        [color= #0000ff;]if [color= #000000;](ret [color= #000000;]== SOCKET_ERROR[color= #000000;])

        [color= #000000;]{

            printf[color= #000000;]([color= #A31515;]"sendto() failed: %d[color= #A31515; font-weight: bold;]n", WSAGetLastError[color= #000000;]([color= #000000;])[color= #000000;]);

            break;

        [color= #000000;]}

        [color= #0000ff;]else

            printf[color= #000000;]([color= #A31515;]"sent %d bytes[color= #A31515; font-weight: bold;]n", ret[color= #000000;]);

    [color= #000000;]}

    closesocket[color= #000000;](s[color= #000000;]);

    WSACleanup[color= #000000;]([color= #000000;]);

 

    [color= #0000ff;]return [color= #ff0000;]0;

[color= #000000;]}

banner_60_468.gif

NOTHING IS IMPOSSIBLE

#2

بالطبع في الكود يجب إضافة المكتبة :

#pragma comment(lib,"ws2_sock32.lib");

لإبتداء خدمات winsock2 ,

المهم في الكود من بدأ الدالة main , وسأوضح بعض النقاط بشكل سريع بإفتراض ان القاريء متآلف مع برمجة الشبكات عموما من الجزء الأول المرفق رابطه في الرد السابق :

لاحظ الجزء التالي في الكود :

s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,0);

أنشئا سوكيت لبروتوكول udp عادي , وبهذا سنغلف البيانات التي سنرسلها ببنية بروتكول IP ثم UDP وليس TCP , حيث أن بنية UDP أسهل من بنية TCP كما هو واضح من الصور المرفقة السابقة ,

ثم مباشرة نحول ال optinos الخاصة بالسوكيت التي أنشئناها لترسل معلومات ال header مع البيانات كل مرة كالتالي :

bOpt = TRUE;
   ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, 
      sizeof(bOpt));

ثم نبدأ بتعبئة البيانات المطلوبة الواحد تلو الآخر :

iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + strlen(strMessage);

هنا iTotalSize سيحتوي على حجم الباكيت كاملة , حيث هي = حجم ال IP Header + حجم Udp Header + حجم ال message المرسلة .بالترتيب .

وبشكل عادي راقب كيفية تعبئة البيانات , وهنا :

 memcpy(ptr, &ipHdr.ip_srcaddr,  sizeof(ipHdr.ip_srcaddr));  
   ptr += sizeof(ipHdr.ip_srcaddr);
   iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);

   memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr)); 
   ptr += sizeof(ipHdr.ip_destaddr);
   iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);

سنحتاج لتعبئة بعض المعلومات لإنشاء ال checksum الخاص بالباكيت "الحزمة" حيث أن checksum هو رقم معرف مميز يحدد صلاحية بيانات الحزمة أو خللها في حال لم تصل كاملة للهدف , والدالة

USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum=0;

    while (size > 1)
    {
        cksum += *buffer++;
        size  -= sizeof(USHORT);   
    }
    if (size)
    {
        cksum += *(UCHAR*)buffer;   
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16); 

    return (USHORT)(~cksum); 
}

تقوم بتحديد ال checksum لحزمة مرسلة , وهذه العملية يجب أن تتم على مستوى كل حزمة بشكل مختلف , حيث أن checksum سيكون مختلف كل مرة .

في النهاية قبل البدأ بإرسال الحزمة :

memcpy(ptr, &ipHdr, sizeof(ipHdr));   ptr += sizeof(ipHdr);
   memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);
   memcpy(ptr, strMessage, strlen(strMessage));

وبعدها نرسل ال buf للمستفيد بالدالة sendto والتي لاتحتاج لعمل Connection حيث تستخدم مع بروتوكولات connectionless Protocol على رأسها Udp , فلا حاجة لإستدعاء الدالة connect فيها .

الآن الطرف المستفيد سيقوم بعمل bind على المنفذ رقم 5150 ثم بالدالة recvfrom مباشرة سنحصل على بيانات buf فيها النص المرسل , وللتأكد من أننا زيفنا ال Header يمكن أن نقرأ عند المستخدم المستفيد مباشرة كالتالي :

ret = recvfrom(s, recvbuf, dwLength, 0, 
                (SOCKADDR *)&sender, &dwSenderSize);
        if (ret == SOCKET_ERROR)
        {
            printf("recvfrom() failed; %d\n", WSAGetLastError());
            break;
        }
        else if (ret == 0)
            break;
        else
        {
            recvbuf[ret] = '\0';
            printf("[%s] sent me: '%s'\n", 
                inet_ntoa(sender.sin_addr), recvbuf);
        }

الآن القيمة sender.sin_addr ستحتوي على عنوان IP المرسل الذي يمكن أن نزوره بكل بساطة لإيهام المستفيد بشيء مختلف !

عموما هنا في الرابط تجد كود كامل منقول كما هو من كتاب NetWork Programming For Microsoft Windows :

http://www.arabteam2000.com/Default.asp?ID=240&Sec=7

وبالنسبة لتحميل نفس الكتاب يمكن تحميله من مكتبة الفريق العربي على الرابط هنا :

http://www.arabteam2000.com/Default.asp?ID=345&Sec=6

سنتابع هنا بعض التقنيات الأخرى وقريبا بإذن الله .

تم تحرير الروابط لأماكنها الجديدة ,,,

تم تعديل هذه المشاركة بواسطة HGB في 20 أغسطس 2006 في 17:57

banner_60_468.gif

NOTHING IS IMPOSSIBLE

#3

بارك الله فيك

أخي سوف تبكي عليك العيون * * * وتـسـأل عـنك دمـوع المـئـين

فإن جف دمعي سيبكي الغمام * * * يـرصـع قـبرك بــالـياسـمـيـن

أخـي مـا يـأسـنـا ولـن نيـأسـا * * * وما طال في القلب لبث الأسى

ومـا حـل أفــئــدة الــمــــؤمـن * * * سـوى أمـل في الـجنـان رسـى

أخي فانتظر ولتعش في غـد * * * سـيـنـبـثـق الأمـل الـسـرمـد

فـإن مـزقـتـنـا سني الــحـيـاة * * * فإنـا مع الـنصـر فـي مـوعــد

#4

موقع أراه ثروة لمن أراد التعمق في هذا المجال .

يذكر الطبقات TCP

و البرتوكولات داخل كل طبقة

و تحليل للباكيت

بالتوفيق للجميع ،،،،

http://www.protocols.com/pbook/tcpip1.htm

أخي سوف تبكي عليك العيون * * * وتـسـأل عـنك دمـوع المـئـين

فإن جف دمعي سيبكي الغمام * * * يـرصـع قـبرك بــالـياسـمـيـن

أخـي مـا يـأسـنـا ولـن نيـأسـا * * * وما طال في القلب لبث الأسى

ومـا حـل أفــئــدة الــمــــؤمـن * * * سـوى أمـل في الـجنـان رسـى

أخي فانتظر ولتعش في غـد * * * سـيـنـبـثـق الأمـل الـسـرمـد

فـإن مـزقـتـنـا سني الــحـيـاة * * * فإنـا مع الـنصـر فـي مـوعــد

#5

بارك الله فيك

52gv0m.gif
#6

السلام عليكم ورحمة الله

شكرا جزيلا على المجهود الرائع

سؤالى ايه افضل طريقة لنقل بيانات بين جهازين عن طريق السى

وما هو افضل بروتوكول

ومثال ياريت

هذا الموضوع مغلق.

مواضيع مشابهة