Thông báo

Collapse
No announcement yet.

Giao thức TCP/IP và Web server với AVR

Collapse
This is a sticky topic.
X
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • #16
    Nguyên văn bởi nttam79 Xem bài viết
    Câu hỏi của em thực ra rất hay, vấn đề này tôi đã không giải thích chi tiết trong phần giao thức ethernet.
    - Giao thức ethernet chỉ hỗ trợ 2 hình thức truyền: unicast: tức là 1 host gửi, 1 host nhận; và broadcast, tức là 1 host gửi, tất cả các host trong mạng LAN đều nhận.

    - Trong mạng LAN cơ bản, sử dụng 1 HUB để kết nối các máy tính với nhau trong mạng LAN. Khi một máy tính gửi đi một frame ethernet, bất kể là nó gửi unicast hay broadcast, thì tất cả các máy tính trong mạng LAN đó (kết nối với HUB) đều nhận được frame đó. Nhưng mỗi máy tính sẽ đối chiếu địa chỉ MAC nhận với địa chỉ của chính nó (ở đây chỉ kiểm tra địa chỉ MAC, không kiểm tra địa chỉ IP, khi lên giao thức IP thì mới kiểm tra địa chỉ IP), và các host sẽ chỉ nhận frame và chuyển lên giao thức IP trong 2 trường hợp:
    + Hoặc địa chỉ là của chính nó
    + Hoặc địa chỉ là broadcast
    - Vậy điều gì sẽ xảy ra nếu một máy tính nào đó phá vỡ luật chơi, nhận dữ liệu không phải dành cho nó, như vậy phải chăng nó có thể nghe trộm dữ liệu gửi cho máy tính khác.
    - Câu trả lời ở đây là: đúng như vậy, mạng LAN kiểu này hoàn toàn không có bảo mật, với các phần mềm nghe trộm dữ liệu, một máy tính có thể nghe trộm dữ liệu của các máy khác trong cùng mạng LAN.
    - Ở đây thiết bị HUB dùng để kết nối các máy tính tạo thành mạng LAN chỉ đơn giản là khi nhận được dữ liệu đến 1 port của nó, nó sẽ khuyếch đại và phát ra lại ở tất cả các port, để tất cả máy tính nối đến nó đều nhận được dữ liệu.

    - Tất nhiên người ta cũng nhận ra hạn chế đó của HUB, cũng như một số hạn chế khác, và phát triển một thiết bị "thông minh" hơn HUB, đó là SWITCH.
    - Về hình thức, SWITCH cũng có nhiều port và dùng để kết nối các máy tính tạo thành mạng LAN giống HUB, tuy nhiên sự khác biệt là: mỗi khi nhận được dữ liệu đến 1 port của nó, SWITCH sẽ kiểm tra địa chỉ MAC đích trên frame, sau đó nó tìm xem máy tính có địa chỉ MAC tương ứng đang nằm ở port nào của nó, và chuyển dữ liệu đến port đó. Như vậy chỉ có máy tính đó nhận được dữ liệu mà thôi.
    Hiện nay hầu hết các mạng LAN là dùng SWITCH, trừ các thiết bị có số port ít (<=5 port) là còn dùng HUB.
    Việc gửi broadcast trên mạng LAN chỉ dùng cho một số trường hợp đặc biệt, ví dụ như cho giao thức ARP, hay khi giao thức IP yêu cầu gửi broadcast (giao thức IP thì có 3 hình thức gửi là unicast, multicast và broadcast). Địa chỉ MAC broadcast được qui định là FF:FF:FF:FF:FF:FF.
    Mặc định, việc gửi broadcast ra ngoài phạm vi mạng LAN là không được phép, các router sẽ chặn các bản tin broadcast và không cho nó ra khỏi phạm vi mạng LAN.

    Hy vọng câu trả lời trên giải đáp được thắc mắc của em, nếu còn chưa rõ cứ hỏi tiếp nhé.
    Dạ, tks Thầy. Em cũng định hỏi tiếp về unicast và brodcast, mà thầy nói lun ròi.
    Thầy có thể tranh thủ, viết rõ hơn về IP và ARP được không ạ. Em thấy phần này khó mà thầy viết hơi tóm tắt, cũng hiểu nhưng không rõ ràng. cụ thể như phần Ethernet.
    Câu hỏi:ARP: Em nghĩ tới 1 cái là: mình ko đánh 192.xxx.x.x nữa mà có thể đánh chữ nào đó như avrnet và Enter thì có hiển thị được webserver không ạ? Và vai trò của ARP trong trường hợp này thế nào.
    Thấy nói kĩ phần này ạ. Mong thầy post bài ít ít một. Tụi em đọc kĩ lắm, từng câu chữ mới hiểu được. Cộng với có thời gian để bàn luận từng phần sẽ không bị loãng nội dung các bài.
    Tks Thầy!

    Comment


    • #17
      Nguyên văn bởi nttam79 Xem bài viết
      Tôi cũng có làm về FPGA trên chip của Xilinx với ngôn ngữ VHDL và Verilog, nếu cần em cứ hỏi
      Vậy thì còn gì bằng,em cũng đang làm trên board của xilinx .thank anh trước.

      Comment


      • #18
        Nguyên văn bởi dinh_dong Xem bài viết
        Câu hỏi:ARP: Em nghĩ tới 1 cái là: mình ko đánh 192.xxx.x.x nữa mà có thể đánh chữ nào đó như avrnet và Enter thì có hiển thị được webserver không ạ? Và vai trò của ARP trong trường hợp này thế nào.
        Lại một câu hỏi rất đáng để bàn luận nữa, tuy nhiên vấn đề này không thuộc giao thức ARP mà thuộc một hệ thống khác, ta gọi là hệ thống tên miền (domain name system).
        Đúng ra, máy tính chỉ gửi và nhận dữ liệu trên mạng dựa vào địa chỉ IP. Tức là lẽ ra để truy cập vào trang chủ yahoo chẳng hạn, ta phải gõ địa chỉ IP server của yahoo: http://98.137.149.56 (các bạn có thể thử).
        Tuy nhiên rõ ràng là cách này quá khó nhớ với người sử dụng, do đó người ta mới nghĩ ra một loại địa chỉ gợi nhớ dễ nhớ hơn, đó là tên miền (domain name) như vậy thay vì gõ: http://98.137.149.56 ta có thể gõ: http://www.yahoo.com.
        Nhưng vấn đề lại phát sinh là máy tính thì không hiểu tên miền, đối với nó thì nhất thiết phải có địa chỉ IP thì mới gửi nhận dữ liệu trên mạng được.
        Vì vậy người ta duy trì trên mạng Internet một hệ thống server gọi là Domain Name System Server, viết tắt là DNS server (nếu chúng ta vào phần cấu hình địa chỉ IP tĩnh cho máy tính sẽ thấy phần này). Nhiệm vụ của các server này là khi có 1 máy tính bất kỳ hỏi nó về một tên miền, nó sẽ trả lời ngay tên miền đó ứng với địa chỉ IP nào.
        Vậy bây giờ, nếu chúng ta mở trình duyệt và gõ vào đó http://www.yahoo.com thì cơ chế sẽ như sau:
        - Máy tính sẽ gửi đi một câu hỏi đến DNS server là: tên miền http://www.yahoo.com thì tương ứng với địa chỉ IP nào?
        - DNS server sẽ trả lời: Tên miền www.yahoo.com tương ứng với địa chỉ IP 98.137.149.56.
        - Máy tính sẽ truy cập theo địa chỉ 98.137.149.56 và tải nội dung trang web yahoo về.

        Vậy để có thể sử dụng tên miền, máy tính bắt buộc phải biết ít nhất một địa chỉ DNS server. Thông tin về DNS server sẽ được cung cấp thông qua giao thức DHCP hoặc cấu hình tĩnh.
        Có rất nhiều DNS server trên mạng, mỗi nhà cung cấp dịch vụ Internet của Việt Nam chẳng hạn đều có 1 vài DNS server. Ví dụ VNPT có các DNS server: 203.162.4.190; 203.162.4.191; 203.162.4.1. Viettel có 203.113.131.1; 203.113.131.2; FPT có 210.245.0.11,...
        Vậy làm cách nào để có được tên miền của riêng mình (ví dụ www.avrnet.vn)? Câu trả lời là phải đăng ký tên miền (trả phí) và trả chi phí hàng năm để duy trì tên miền. Lúc đó ta có quyền chỉ định tên miền đó tương ứng với địa chỉ IP nào.
        Nếu không có điều kiện mua tên miền, ta có thể sử dụng 1 số tên miền miễn phí (ví dụ của dyndns). Đó là cách mà ta sẽ dùng cho project này (đến phần cuối cùng nhé).
        Last edited by nttam79; 03-11-2011, 10:31.

        Comment


        • #19
          Thầy có thể so sánh Add luận lí và Add MAC được không ạ?
          Tại sao trương MAC đích khi truyền ra internet lại là địa chỉ Gateway? gateway giống MAC ở điểm nào, mà lại đc điền vào MAC đích?
          Và ARP cache có giống với bảng NAT ip không ạ? Em thấy na lá. Có phải Gateway and local IP(mạng LAN) của host sẽ cho địa chỉ MAC của host đích không ạ?
          Mong thầy trả lời!

          Comment


          • #20
            Liên quan tới DHCP gì đó. Sr vì em ko nhớ rõ.
            Hệ thống bây giờ em mún gắn thêm Moderm kết nối board, PC. Thì cần giao thức DHCP gi gì không ạ. Và cần cấu hình ntn? Thầy có hướng dẫn lun phần này trong project này không ạ?

            Comment


            • #21
              À quên mất, còn 1 cách nữa, đơn giản hơn, nhưng chỉ làm được trên từng máy tính thôi. Đó là trên mỗi máy tính có lưu trữ 1 file chứa tên host và địa chỉ IP tương ứng. File này có tên là hosts, và nằm ở đường dẫn "c:\windows\system32\drivers\etc\hosts". Ta có thể mở file này và thêm vào 1 dòng: ví dụ "96.17.180.162 www.avrnet.vn". Lúc đó máy tính sẽ hiểu tên đó thì tương ứng với địa chỉ IP như vậy. Nhưng cách này chỉ có tác dụng trên máy tính mà ta sửa file hosts thôi.

              Comment


              • #22
                Nguyên văn bởi dinh_dong Xem bài viết
                Thầy có thể so sánh Add luận lí và Add MAC được không ạ?
                Tại sao trương MAC đích khi truyền ra internet lại là địa chỉ Gateway? gateway giống MAC ở điểm nào, mà lại đc điền vào MAC đích?
                Và ARP cache có giống với bảng NAT ip không ạ? Em thấy na lá. Có phải Gateway and local IP(mạng LAN) của host sẽ cho địa chỉ MAC của host đích không ạ?
                Mong thầy trả lời!
                Để hiểu về 2 loại địa chỉ ta có thể hình dung như thế này:
                Giả sử ta cần gửi 1 bức thư loanh quanh trong xóm, ta chỉ cần ghi tên người nhận là được, trong xóm sẽ dễ dàng xác định ông Nguyễn Văn A ở chỗ nào.
                Tuy nhiên khi gửi thư đi trong phạm vi cả nước, nếu ta chỉ ghi tên người nhận, thậm chí có thêm cả ngày tháng năm sinh và số chứng minh thư để bảo đảm không sợ bị trùng, thì bưu điện cũng bó tay vì không biết ông Nguyễn Văn A ở đâu, vì với địa chỉ này (gồm tên, ngày tháng năm sinh, số chứng minh thư) thì dù không sợ trùng địa chỉ, thì nó cũng không thể giúp ta xác định được ông Nguyễn Văn A đang ở tỉnh, thành phố, đường nào.
                Vậy ta cần một cách ghi địa chỉ khác, mà nhìn vào ta xác định được nơi cần chuyển thư tới, ví dụ tỉnh... huyện.... đường.... số nhà.
                Điều này hoàn toàn tương tự với địa chỉ IP và địa chỉ MAC: địa chỉ MAC mặc dù là bảo đảm không trùng nhau, nhưng nhìn vào nó ta không thể biết host có địa chỉ MAC đó đang ở đâu? Mỹ, Việt Nam hay Trung Quốc,...? Do đó địa chỉ MAC chỉ sử dụng được trong mạng LAN, nơi số lượng máy tính là ít, các thiết bị như SWITCH có thể biết hết các địa chỉ MAC trong mạng.
                Để gửi dữ liệu ra ngoài mạng LAN, ta cần 1 loại địa chỉ khác, một địa chỉ mà khi nhìn vào ta biết ngay là host tương ứng đang ở Mỹ hay Việt Nam, thậm chí nếu ở Việt Nam thì thuộc mạng của nhà cung cấp dịch vụ nào. Địa chỉ thõa mãn yêu cầu này chính là địa chỉ IP.
                Sở dĩ như vậy vì trong địa chỉ IP, người ta chia thành 2 phần, phần đầu là địa chỉ mạng, cho biết máy tính đó đang thuộc mạng nào, phần sau là địa chỉ host, giúp phân biệt các máy tính trong mạng.
                Ta có thể dễ dàng nhận thấy điều này: các máy tính trong cùng mạng thì phần đầu của địa chỉ IP là giống nhau.
                Nhìn vào 1 địa chỉ IP, ta sẽ biết ngay máy tính tương ứng đang ở nước nào.
                Trong phạm vi mạng LAN, việc chuyển dữ liệu đến đích về mặt vật lý hoàn toàn chỉ cần dựa vào HUB hay SWITCH, tuy nhiên khi gửi ra ngoài mạng LAN thì HUB hay SWITCH sẽ bó tay, vì sẽ không biết được địa chỉ MAC của máy tính bên ngoài. Lúc này, HUB hay SWITCH sẽ chuyển gói tin đến một thiết bị khác có khả năng đưa gói tin ra khỏi mạng LAN, đó chính là Gateway, thiết bị kết nối giữa mạng LAN với bên ngoài. Và rõ ràng để SWITCH chuyển gói tin đến Gateway, thì bây giờ địa chỉ MAC đích trong frame ethernet phải là địa chỉ MAC của Gateway.
                ARP cache hoàn toàn khác bảng NAT IP (NAT-Network Address Translation)
                Trong project này sẽ hướng dẫn đến kết nối, cài đặt modem, đăng ký tên miền, thiết kế website,... nói chung từ A-Z luôn.
                Last edited by nttam79; 03-11-2011, 02:13.

                Comment


                • #23
                  Nguyên văn bởi nttam79 Xem bài viết
                  Để hiểu về 2 loại địa chỉ ta có thể hình dung như thế này:
                  Giả sử ta cần gửi 1 bức thư loanh quanh trong xóm, ta chỉ cần ghi tên người nhận là được, trong xóm sẽ dễ dàng xác định ông Nguyễn Văn A ở chỗ nào.
                  Tuy nhiên khi gửi thư đi trong phạm vi cả nước, nếu ta chỉ ghi tên người nhận, thậm chí có thêm cả ngày tháng năm sinh và số chứng minh thư để bảo đảm không sợ bị trùng, thì bưu điện cũng bó tay vì không biết ông Nguyễn Văn A ở đâu, vì với địa chỉ này (gồm tên, ngày tháng năm sinh, số chứng minh thư) thì dù không sợ trùng địa chỉ, thì nó cũng không thể giúp ta xác định được ông Nguyễn Văn A đang ở tỉnh, thành phố, đường nào.
                  Vậy ta cần một cách ghi địa chỉ khác, mà nhìn vào ta xác định được nơi cần chuyển thư tới, ví dụ tỉnh... huyện.... đường.... số nhà.
                  Điều này hoàn toàn tương tự với địa chỉ IP và địa chỉ MAC: địa chỉ MAC mặc dù là bảo đảm không trùng nhau, nhưng nhìn vào nó ta không thể biết host có địa chỉ MAC đó đang ở đâu? Mỹ, Việt Nam hay Trung Quốc,...? Do đó địa chỉ MAC chỉ sử dụng được trong mạng LAN, nơi số lượng máy tính là ít, các thiết bị như SWITCH có thể biết hết các địa chỉ MAC trong mạng.
                  Để gửi dữ liệu ra ngoài mạng LAN, ta cần 1 loại địa chỉ khác, một địa chỉ mà khi nhìn vào ta biết ngay là host tương ứng đang ở Mỹ hay Việt Nam, thậm chí nếu ở Việt Nam thì thuộc mạng của nhà cung cấp dịch vụ nào. Địa chỉ thõa mãn yêu cầu này chính là địa chỉ IP.
                  Sở dĩ như vậy vì trong địa chỉ IP, người ta chia thành 2 phần, phần đầu là địa chỉ mạng, cho biết máy tính đó đang thuộc mạng nào, phần sau là địa chỉ host, giúp phân biệt các máy tính trong mạng.
                  Ta có thể dễ dàng nhận thấy điều này: các máy tính trong cùng mạng thì phần đầu của địa chỉ IP là giống nhau.
                  Nhìn vào 1 địa chỉ IP, ta sẽ biết ngay máy tính tương ứng đang ở nước nào.
                  Trong phạm vi mạng LAN, việc chuyển dữ liệu đến đích về mặt vật lý hoàn toàn chỉ cần dựa vào HUB hay SWITCH, tuy nhiên khi gửi ra ngoài mạng LAN thì HUB hay SWITCH sẽ bó tay, vì sẽ không biết được địa chỉ MAC của máy tính bên ngoài. Lúc này, HUB hay SWITCH sẽ chuyển gói tin đến một thiết bị khác có khả năng đưa gói tin ra khỏi mạng LAN, đó chính là Gateway, thiết bị kết nối giữa mạng LAN với bên ngoài. Và rõ ràng để SWITCH chuyển gói tin đến Gateway, thì bây giờ địa chỉ MAC đích trong frame ethernet phải là địa chỉ MAC của Gateway.
                  ARP cache hoàn toàn khác bảng NAT IP (NAT-Network Address Translation)
                  Trong project này sẽ hướng dẫn đến kết nối, cài đặt modem, đăng ký tên miền, thiết kế website,... nói chung từ A-Z luôn.
                  Dạ, tks Thầy.

                  Comment


                  • #24
                    Nguyên văn bởi nttam79 Xem bài viết
                    Trong project này sẽ hướng dẫn đến kết nối, cài đặt modem, đăng ký tên miền, thiết kế website,... nói chung từ A-Z luôn.
                    Ôi quá hay rồi. Gặp cao thủ .
                    Tiện đây anh cho em hỏi luôn nhá:
                    Em đang muốn làm một website để build nó thành file .C lưu vào falsh ROM bằng cách sử dụng MPFS.exe của Microchip nhưng em đọc tài liệu mà chưa thấy chỗ nào hướng dẫn cụ thể về cách thực hiện cả về việc xây dưng trang web(chỉ với vài nút bấm và vài dòng text), cách lưu trang web vào ROM và cách truyền theo FTP để tải trang web lên web browser.
                    Phần này em hỏi có vẻ chưa đúng thời điểm nên nếu khi nào có thể thì nhờ anh chỉ giúp em. Tks anh !

                    Comment


                    • #25
                      Bài viết của anh Nguyễn Thanh Tâm rất hay, em đang theo dõi và chờ đợi anh viết từng ngày luôn . Hy vọng sau bài viết này em có thể hoàn thành được Project mà bỏ dở gần 1 năm qua vì bí phần giao thức TCP/IP và không biết lập trình web thế nào để nhúng vô con VĐK. Giờ đã hình dung được rùi hehe.

                      Email:
                      Tel: 0983.497.310

                      Comment


                      • #26
                        Có lẽ mình cần dừng lại để giải thích rõ hơn về hoạt động của 2 giao thức IP và ARP một chút, cũng như các sử dụng 2 loại địa chỉ IP và MAC trên mạng, trước khi viết code tiếp, tuy hơi dài dòng 1 chút nhưng sẽ giúp mọi người hiểu rõ hơn cách thức làm việc của TCP/IP, như vậy thì sẽ dễ hiểu code hơn và có thể tự viết hay sửa đổi code được dễ dàng.

                        Ta hãy xem xét 1 mạng ví dụ như sau:
                        - Mạng LAN tại nhà gồm 3 máy tính và 1 board mạch của chúng ta kết nối vào ADSL router, từ đó nối vào mạng của nhà cung cấp dịch vụ.
                        - Các bạn cũng cần biết là thực ra modem ADSL hay ADSL router mà ta dùng ở nhà, thật ra bên trong nó gồm 3 thiết bị: một HUB để mở rộng số lượng port, cho phép nhiều máy tính có thể cùng kết nối vào mạng; một Router IP đóng vai trò Gateway, thực hiện chức năng định tuyến giữa mạng bên trong (LAN) và mạng bên ngoài (WAN); và cuối cùng là 1 modem (Modulation - Demodulation) để có thể truyền dữ liệu trên đường dây ADSL.

                        Ta xẽ xem xét 2 ví dụ:
                        Ví dụ A: board mạch của chúng ta gửi dữ liệu đến 1 máy tính trong cùng mạng LAN, ví dụ là máy có địa chỉ 192.168.1.6.
                        Ví dụ B: board mạch gửi dữ liệu đến 1 máy tính nằm bên ngoài, ví dụ là máy có địa chỉ 203.162.44.164
                        A-Trường hợp gửi trong mạng LAN
                        Bước 1: Giao thức IP trong board mạch nhận được yêu cầu gửi dữ liệu đến địa chỉ IP 192.168.1.6
                        Bước 2: Nó đi hỏi giao thức ARP (thông qua hàm ArpIpOut) về địa chỉ này. ARP sau khi tìm trong bảng ARP cache không thấy, nó sẽ gửi 1 bản tin ARP request dưới hình thức broadcast đến mọi máy tính trong mạng. Máy tính có địa chỉ tương ứng sẽ trả lời.


                        Bước 3: ARP sẽ cập nhật bảng ARP cache và trả lời lại cho giao thức IP.
                        Bước 4: giao thức IP dùng thông tin này để điền vào frame ethernet và chuyển sang giao thứ ethernet để gửi đi.


                        B-Trường hợp gửi ra ngoài mạng LAN
                        Nếu vẫn làm theo cách cũ thì sẽ xảy ra trường hợp như sau:




                        Như vậy, nếu vẫn làm theo cách cũ, việc gửi dữ liệu sẽ thất bại.
                        Mọi việc phải được tiến hành như sau:




                        Có ai biết cách post flash lên forum không? Xin chỉ giúp. Vài minh họa bằng ảnh động có lẽ dễ hiểu hơn.
                        Last edited by nttam79; 03-11-2011, 14:28.

                        Comment


                        • #27
                          Vậy bây giờ ta bắt đầu viết code cho các giao thức ip và arp:
                          Ta tạo file “ip.c” với nội dung ban đầu”
                          Code:
                          //----------------------------------------------------------------------------
                          // Writen by NTTam - PTITHCM
                          //----------------------------------------------------------------------------
                          #include <avr/io.h>
                          #include "packet.h"
                          #include "ethernet.h"
                          #include "arp.h"
                          #include "ip.h"
                          Và file header “ip.h”
                          Code:
                          //----------------------------------------------------------------------------
                          // Writen by NTTam - PTITHCM
                          //----------------------------------------------------------------------------
                          #ifndef IP_H
                          #define IP_H
                          
                          #endif //IP_H
                          Ta cũng tạo 2 file tương ứng cho giao thức ARP:
                          “arp.c”
                          Code:
                          //----------------------------------------------------------------------------
                          // Writen by NTTam - PTITHCM
                          //----------------------------------------------------------------------------
                          #include <avr/io.h>
                          #include "packet.h"
                          #include "ethernet.h"
                          #include "arp.h"
                          #include "ip.h"
                          “arp.h”
                          Code:
                          //----------------------------------------------------------------------------
                          // Writen by NTTam - PTITHCM
                          //----------------------------------------------------------------------------
                          #ifndef ARP_H
                          #define ARP_H
                          //----------------------------------------------------------------------------
                          
                          #endif //ARP_H
                          Như ta thấy ở trên, để giao thức IP hoạt động, nó cần biết một số thông tin cơ bản:
                          - Địa chỉ IP của nó.
                          - Subnet Mask của nó (có thời gian se giải thích Subnet mask sau).
                          - Địa chỉ IP của Gateway.
                          - Địa chỉ MAC của nó.
                          Ta sẽ lưu các thông tin này trong một biến kiểu struct là ipConfig. Mở file “ip.h”, khai báo kiểu struct này vào:
                          Code:
                          //----------------------------------------------------------------------------
                          #include "packet.h"
                          
                          struct ipConfig				///< IP addressing/configuration structure
                          {
                          	unsigned long ip;			///< IP address
                          	unsigned long netmask;		///< netmask
                          	unsigned long gateway;		///< gateway IP address
                          	struct ntEthAddr ethaddr;
                          };
                          Mở tiếp file “ip.c”, khai báo biến IpMyConfig có kiểu là struct ipConfig
                          Code:
                          //--------------------------------------------------------------------------------------
                          struct ipConfig IpMyConfig;	///< Local IP address/config structure
                          Tiếp theo ta viết trong file “ip.c” một số hàm chức năng cho giao thức này:
                          Đầu tiên là hàm để tính trường kiểm tra lỗi (checksum) trong Header IP. Nếu các bạn xem lại phần cấu trúc Header của IP sẽ thấy nó có 1 trường kiểm tra lỗi cho Header (không bao gồm data). Trường này giúp phía nhận gói IP kiểm tra lại xem thông tin chứa trong Header (rất quan trọng) có bị sai trong quá trình truyền hay không. Nếu có sai sót, gói tin đó sẽ bị hủy bỏ mà không xử lý.
                          Phía phát trước khi gửi phải tính giá trị checksum và ghi nó vào trường checksum trong header. Phía thu khi nhận gói tin sẽ tự mình tính lại check sum 1 cách độc lập, sau đó so sánh với checksum mà phía phát đã tính (lưu trong header) nếu có khác biệt thì tức là có lỗi xảy ra, và gói tin sẽ bị hủy.
                          Vậy hàm này sẽ được giao thức IP sử dụng cả khi gửi và nhận gói tin.
                          Code:
                          //--------------------------------------------------------------------------------------
                          //Ham tinh checksum cho goi ip
                          unsigned int ipChecksum(unsigned char *data, unsigned int len)
                          {
                              register unsigned long sum = 0;
                          
                              for (;;) {
                                  if (len < 2)
                                      break;
                          		sum += *((unsigned int *)data);
                          		data+=2;
                                  len -= 2;
                              }
                              if (len)
                                  sum += *(unsigned char *) data;
                          
                              while ((len = (unsigned int) (sum >> 16)) != 0)
                                  sum = (unsigned int) sum + len;
                          
                              return (unsigned int) sum ^ 0xFFFF;
                          }
                          Ngoài lề 1 tý: khi lập trình project này, viết đến phần tính checksum mình đã tính sai, dẫn đến gói IP không hợp lệ. Phải dùng phần mềm Wireshark bắt từng gói tin, kiểm tra lại từng bit và tính lại checksum bằng tay để sửa, mất chừng 4 tiếng cho riêng phần checksum này.

                          Tiếp theo là hàm để set các giá trị trong struct ipConfig:
                          Code:
                          //--------------------------------------------------------------------------------------
                          //Set cac gia tri cau hinh cho giao thuc ip
                          void ipSetConfig(unsigned long myIp, unsigned long netmask, unsigned long gatewayIp)
                          {
                          	/*
                          	// set local addressing
                          	IpMyConfig.ip = myIp;
                          	IpMyConfig.netmask = netmask;
                          	IpMyConfig.gateway = gatewayIp;
                          	ethGetMacAddress(IpMyConfig.ethaddr.addr);
                          	*/
                          	struct ntEthAddr ethaddr;
                          
                          	// set local addressing
                          	IpMyConfig.ip = myIp;
                          	IpMyConfig.netmask = netmask;
                          	IpMyConfig.gateway = gatewayIp;
                          
                          	// set ARP association
                          	ethGetMacAddress(ethaddr.addr);
                          	arpSetAddress(&ethaddr, myIp);
                          
                          }
                          Hàm trả lại biến con trỏ đến struct lưu thông tin config cho IP, hàm này nhằm giúp các module khác truy xuất được tới biến ipConfig thuộc module ip.
                          Code:
                          //--------------------------------------------------------------------------------------
                          //Tra lai con tro den struct ipConfig
                          struct ipConfig* ipGetConfig(void)
                          {
                          	return &IpMyConfig;
                          }
                          Hàm in ra địa chỉ MAC (dùng trong debug hoặc khi config board mạch qua cổng nối tiếp bằng command line.
                          Code:
                          //--------------------------------------------------------------------------------------
                          //In ra dia chi ethernet
                          void ethPrintAddr(struct ntEthAddr* ethAddr)
                          {
                          	printf("%x:%x:%x:%x:%x:%x",(ethAddr->addr[0]),(ethAddr->addr[1]),(ethAddr->addr[2]),\
                          		(ethAddr->addr[3]),(ethAddr->addr[4]),(ethAddr->addr[5]));
                          }
                          Tương tự là hàm in ra địa chỉ IP
                          Code:
                          //--------------------------------------------------------------------------------------
                          //In ra dia chi IP
                          void ipPrintAddr(unsigned long ipaddr)
                          {
                          	printf("%d.%d.%d.%d",
                          		((unsigned char*)&ipaddr)[3],
                          		((unsigned char*)&ipaddr)[2],
                          		((unsigned char*)&ipaddr)[1],
                          		((unsigned char*)&ipaddr)[0]);
                          }
                          Và hàm in ra các thông số cấu hình IP
                          Code:
                          //--------------------------------------------------------------------------------------
                          //In ra cac gia tri cau hinh cho giao thuc IP
                          void ipPrintConfig(struct ipConfig* config)
                          {
                          	printf("IP Addr : "); ipPrintAddr(config->ip);		printf("\n\r");
                          	printf("Netmask : "); ipPrintAddr(config->netmask);	printf("\n\r");
                          	printf("Gateway : "); ipPrintAddr(config->gateway);	printf("\n\r");
                          }
                          Lưu ý: để truy xuất được các hàm trong module “ethernet.c”, chúng ta phải thêm phần khai báo (declare) các hàm này vào file header tương ứng “ethernet.h” nhé. Từ nay việc này là đương nhiên, mình sẽ không nhắc lại nữa.
                          Ta có sử dụng hàm printf để xuất dữ liệu ra cổng COM, các bạn tự viết nhé.
                          Một số hàm thuộc module giao thức ARP, ta vẫn chưa viết, được gọi ở đây, nên sẽ tạo thông báo lỗi thiếu hàm khi biên dịch.

                          Trên đây là một số hàm công cụ cung cấp các chức năng hỗ trợ cho giao thức IP. Tiếp theo sẽ là những hàm xử lý chính trong giao thức IP, bao gồm hàm gửi và nhận gói tin IP.

                          Ta viết tiếp hàm thực hiện gửi 1 gói tin qua giao thức IP:
                          Code:
                          //--------------------------------------------------------------------------------------
                          //Ham gui 1 goi IP
                          void ipSend(unsigned long dstIp, unsigned char protocol, unsigned int len, unsigned char* ipData)
                          {
                          	struct ntEthHeader* ethHeader;
                          	struct ntIPHeader* ipHeader;
                          	ipHeader = (struct ntIPHeader*)(ipData - IP_HEADER_LEN);
                          	ethHeader = (struct ntEthHeader*)(ipData - IP_HEADER_LEN - ETH_HEADER_LEN);
                          	len += IP_HEADER_LEN;
                          
                          	ipHeader->desIPAddr = HTONL(dstIp);
                          	ipHeader->srcIPAddr = HTONL(IpMyConfig.ip);
                          	ipHeader->Protocol = protocol;
                          	ipHeader->Len = HTONS(len);
                          	ipHeader->verHdrLen = 0x45;
                          	ipHeader->ToS = 0;
                          	ipHeader->IDNumber = 0;
                          	ipHeader->Offset = 0;
                          	ipHeader->TTL = IP_TIME_TO_LIVE;
                          	ipHeader->Checksum = 0;
                          
                          	ipHeader->Checksum = ipChecksum((unsigned char*)ipHeader, IP_HEADER_LEN);
                          	if( (dstIp & IpMyConfig.netmask) == (IpMyConfig.ip & IpMyConfig.netmask) )
                          	{
                          		arpIpOut((unsigned char*)ethHeader,0);					// local send
                          	}
                          	else
                          	{
                          		arpIpOut((unsigned char*)ethHeader,IpMyConfig.gateway);	// gateway send
                          	}
                          	len += ETH_HEADER_LEN;
                          	#ifdef IP_DEBUG
                          	printf("Sending IP packet\r\nAddr: ");
                          	ipPrintAddr(dstIp);printf("\n\rMAC: ");
                          	ethPrintAddr(&(ethHeader->desAddr));
                          	#endif
                          	ethSendFrame(len, (unsigned char*)ethHeader);
                          }
                          Giải thích:
                          - Khi hàm này được gọi, có nghĩa là giao thức lớp trên (TCP hay UDP) đã chuẩn bị sẵn dữ liệu cần gửi đi (phần data của gói IP) và đặt lên buffer (ethernet buffer). Vậy trong hàm này ta cần điền đầy đủ thông tin để tạo nên Header IP và gọi hàm của giao thức ethernet (ethSendFrame) để yêu cầu giao thức ethernet gửi gói tin này đi.
                          - Như vậy ở phần đầu, ta trỏ 2 biến con trỏ có kiểu là IP Header và Ethernet Header đến các vị trí tương ứng trên buffer. Sau đó lần lượt tính toán và điền các giá trị của các trường trong Header IP vào.
                          - Tiếp theo ta gọi giao thức ARP để phân giải địa chỉ. Lúc này sẽ có 2 trường hợp: nếu địa chỉ mạng trong địa chỉ IP đích giống của chúng ta, tức là host đích nằm trong cùng mạng LAN, ta sẽ yêu cầu ARP tìm địa chỉ MAC đích để điền vào frame ethernet và gửi đi (hàm ArpIpOut). Nếu khác địa chỉ mạng, tức là host đích nằm bên ngoài mạng LAN, ta sẽ yêu cầu ARP tìm địa chỉ MAC của gateway và điền vào frame ethernet.
                          - Sau đó ta gọi hàm của giao thức ethernet để gửi dữ liệu đi.

                          Trong hàm này, ta có sử dụng 1 giá trị là TTL (Time To Live) để điền vào trường TTL trong Header IP (xem lại cấu trúc Header IP). Giá trị này cần được định nghĩa trước. Ta thêm định nghĩa này vào file “ip.h”:
                          Code:
                          #define IP_TIME_TO_LIVE		128		//gia tri Time-To-Live (TTL) mặc định cho header IP
                          Có thời gian sẽ giải thích ý nghĩa của trường TTL sau nhé.


                          Và hàm xử lý khi nhận được 1 gói tin IP:
                          Code:
                          //--------------------------------------------------------------------------------------
                          //Ham xu ly goi IP, duoc goi boi giao thuc ethernet khi paket type duoc xac dinh la IP
                          void IPProcess(unsigned int len, struct ntIPHeader* packet)
                          {
                          	// check IP addressing, stop processing if not for me and not a broadcast
                          	if( (HTONL(packet->desIPAddr) != ipGetConfig()->ip) &&
                          		(HTONL(packet->desIPAddr) != (ipGetConfig()->ip|ipGetConfig()->netmask)) &&
                          		(HTONL(packet->desIPAddr) != 0xFFFFFFFF) ) 
                          		return;
                          
                          	// handle ICMP packet
                          	if( packet->Protocol == IP_PROTO_ICMP )
                          	{
                          		#ifdef IP_DEBUG
                          		printf("IP->Rx: ICMP/IP packet\r\n");
                          		//icmpPrintHeader((icmpip_hdr*)packet);
                          		#endif
                          		icmpIpIn((struct ntIPHeader*)packet);
                          	}
                          	else if( packet->Protocol == IP_PROTO_UDP )
                          	{
                          		#ifdef IP_DEBUG
                          		printf("IP->Rx: UDP/IP packet\r\n");
                          		//debugPrintHexTable(NetBufferLen-14, &NetBuffer[14]);
                          		#endif
                          		UDPProcess(len, ((struct ntIPHeader*)packet) );
                          	}
                          	else if( packet->Protocol == IP_PROTO_TCP )
                          	{
                          		#ifdef IP_DEBUG
                          		printf("IP->Rx: TCP/IP packet\r\n");
                          		#endif
                          		TCPProcess((unsigned char *)packet,len-((packet->verHdrLen & 0x0F)<<2));
                          	}
                          	else
                          	{
                          		#ifdef IP_DEBUG
                          		printf("IP->Rx: IP packet\r\n");
                          		#endif
                          	}
                          }
                          //--------------------------------------------------------------------------------------
                          Giải thích:
                          - Khi nhận được 1 gói IP, việc đầu tiên giao thức IP cần làm là kiểm tra lại địa chỉ IP xem có phải là gửi cho mình không: và ta chỉ nhận nếu đúng địa chỉ hoặc địa chỉ là IP broadcast (lưu ý đây là địa chỉ IP broadcast (255.255.255.255) nhé, không phải MAC broadcast).
                          - Mặc dù trước đó, giao thức ethernet đã kiểm tra địa chỉ MAC rồi, nhưng giao thức IP vẫn kiểm tra lại địa chỉ IP.
                          - Tiếp theo, ta kiểm tra trường protocol trong header IP để xem giao thức lớp trên (trên giao thức IP) nào đã gửi gói tin này (TCP, UDP, hay ICMP) và gọi hàm của giao thức tương ứng để xử lý.

                          Vậy là xong giao thức IP.

                          Tiếp theo ta viết code cho giao thức ARP.
                          Trước hết ta cần xác định một số giá trị hằng dành cho giao thức ARP. Đó là số dòng tối đa trong bảng ARP cache, thời gian timeout cho mỗi cặp địa chỉ trong bảng ARP cache.
                          Ta mở file “arp.h” thêm vào các định nghĩa này:
                          Code:
                          //--------------------------------------------------------------------------------------
                          #include "packet.h"
                          //--------------------------------------------------------------------------------------
                          #ifndef ARP_TABLE_SIZE
                          #define ARP_TABLE_SIZE	8
                          #endif
                          
                          #ifndef ARP_CACHE_TIME_TO_LIVE
                          #define ARP_CACHE_TIME_TO_LIVE	250
                          #endif
                          Ta cũng khai báo trong “arp.h” một biến kiểu struct cho mỗi dòng trong bảng ARP cache, gồm 1 địa chỉ IP và địa chỉ MAC tương ứng với địa chỉ IP đó:
                          Code:
                          //--------------------------------------------------------------------------------------
                          struct ARPentry
                          {
                          	unsigned long ipAddr;			///< remote-note IP address
                          	struct ntEthAddr ethAddr;	///< remote-node ethernet (hardware/mac) address
                          	unsigned char time;				///< time to live (in ARP table); this is decremented by arpTimer()
                          };
                          Trong mỗi entry, còn có thêm 1 biến là timeout. Như đã nói ở phần trước, mỗi entry trong ARP cache không tồn tại mãi có 1 thời gian timeout nhất định, biến timeout này sẽ được gán 1 giá trị ban đầu mỗi khi được cập nhật, và sẽ tự động giảm theo thời gian (nhờ sử dụng ngắt timer). Nếu 1 entry quá lâu mà không được cập nhật (biến timeout giảm về 0) thì nó sẽ bị xóa đi (thực ra ta không cần xóa mà chỉ cần xem các entry có biến timeout = 0 là entry trống).

                          Ta quay lại file “arp.c”, khai báo một ARPentry để lưu cặp địa chỉ IP – địa chỉ MAC của chính board mạch và một array của ARPentry để làm bảng ARP cache:
                          Code:
                          //--------------------------------------------------------------------------------------
                          struct ARPentry ARPMyAddr;
                          struct ARPentry ARPTable[ARP_TABLE_SIZE];
                          Tiếp theo ta viết các hàm cho giao thức ARP:
                          Đầu tiên là hàm khởi tạo giao thức ARP (thực chất là khởi động giá trị các biến trong ARP cache mà thôi):
                          Code:
                          //--------------------------------------------------------------------------------------
                          void arpInit(void)
                          {
                          	unsigned char i;
                          	for(i=0; i<ARP_TABLE_SIZE; i++)
                          	{
                          		ARPTable[i].ipAddr = 0;
                          		ARPTable[i].time = 0;
                          	}
                          }
                          Hàm set địa chỉ, thực ra chỉ là khai báo địa chỉ MAC và IP của bản thân cho ARP:
                          Code:
                          //--------------------------------------------------------------------------------------
                          void arpSetAddress(struct ntEthAddr* ethAddr, unsigned long ipAddr)
                          {
                          	ARPMyAddr.ethAddr = *ethAddr;
                          	ARPMyAddr.ipAddr = ipAddr;
                          }
                          Hàm tìm kiếm 1 địa chỉ IP trong bảng ARP cache, trả lại vị trí của entry tương ứng với địa chỉ IP đó trong bảng ARP cache:
                          Code:
                          //--------------------------------------------------------------------------------------
                          unsigned char arpSearchIP(unsigned long ipaddr)
                          {
                          	unsigned char i;
                          	for(i=0; i<ARP_TABLE_SIZE; i++)
                          	{
                          		if((ARPTable[i].ipAddr == ipaddr) && (ARPTable[i].time != 0))
                          		{
                          			return i;
                          		}
                          	}
                          	return -1;
                          }
                          Hàm cập nhật 1 entry trong bảng ARP
                          Code:
                          //--------------------------------------------------------------------------------------
                          void arpUpdateEntry(struct ntEthAddr ethAddr,unsigned long ipAddr)
                          {
                          	unsigned char index;
                          	index = arpSearchIP(ipAddr);
                          	if(index < ARP_TABLE_SIZE)
                          	{
                          		ARPTable[index].ethAddr = ethAddr;
                          		ARPTable[index].time = ARP_CACHE_TIME_TO_LIVE;
                          		#ifdef ARP_DEBUG
                          		printf("Update ARP TTL %d: ",index);ipPrintAddr(ipAddr);
                          		printf("-");ethPrintAddr(&ethAddr);printf("\n\r");
                          		#endif
                          		return;
                          	}
                          	for(index=0; index<ARP_TABLE_SIZE; index++)
                          	{
                          		if(!ARPTable[index].time)
                          		{
                          			ARPTable[index].ethAddr = ethAddr;
                          			ARPTable[index].ipAddr = ipAddr;
                          			ARPTable[index].time = ARP_CACHE_TIME_TO_LIVE;
                          			#ifdef ARP_DEBUG
                          			printf("Update ARP: ");ipPrintAddr(ipAddr);
                          			printf("-");ethPrintAddr(&ethAddr);printf("\n\r");
                          			#endif
                          			return;
                          		}
                          	}
                          }
                          Hàm xử lý khi nhận được 1 bản tin ARP (do lớp giao thức ethernet chuyển đến):
                          Code:
                          //--------------------------------------------------------------------------------------
                          void arpArpProcess(unsigned int len, unsigned char* ethFrame)
                          {
                          	struct ntEthHeader* ethHeader;
                          	struct ntARPHeader* arpHeader;
                          	ethHeader = (struct ntEthHeader*)ethFrame;
                          	arpHeader = (struct ntARPHeader*)(ethFrame + ETH_HEADER_LEN);
                          	#ifdef ARP_DEBUG
                          	printf("Received ARP Request\r\n");
                          	arpPrintHeader(arpHeader);
                          	#endif
                          	if(	(arpHeader->hwType == 0x0100) &&
                          		(arpHeader->protocol == 0x0008)  &&
                          		(arpHeader->hwLen == 0x06) && 
                          		(arpHeader->protoLen == 0x04) &&
                          		(arpHeader->dipaddr == HTONL(ARPMyAddr.ipAddr))){
                          		if(arpHeader->opcode == HTONS(ARP_OPCODE_REQUEST)){
                          			arpUpdateEntry(arpHeader->shwaddr,HTONL(arpHeader->sipaddr));
                          			arpHeader->dhwaddr = arpHeader->shwaddr;
                          			arpHeader->dipaddr = arpHeader->sipaddr;
                          			arpHeader->shwaddr = ARPMyAddr.ethAddr;
                          			arpHeader->sipaddr = HTONL(ARPMyAddr.ipAddr);
                          			arpHeader->opcode = HTONS(ARP_OPCODE_REPLY);
                          			ethHeader->desAddr = ethHeader->srcAddr;
                          			ethHeader->srcAddr  = ARPMyAddr.ethAddr;
                          			#ifdef ARP_DEBUG
                          			printf("Sending ARP Reply\r\n");
                          			arpPrintHeader(arpHeader);
                          			#endif
                          			ethSendFrame(len, (unsigned char*)ethHeader);
                          			return;
                          		}
                          		if(arpHeader->opcode == HTONS(ARP_OPCODE_REPLY)){
                          			arpUpdateEntry(arpHeader->shwaddr,HTONL(arpHeader->sipaddr));
                          			#ifdef ARP_DEBUG
                          			printf("is ARP reply\r\n");
                          			#endif
                          			return;
                          		}
                          	}
                          	#ifdef ARP_DEBUG
                          	printf("Unknown ARP packet\r\n");
                          	#endif
                          }
                          hàm xử lý khi nhận được 1 gói IP: như đã nói trước đây trong nội dung về ARP, có 2 cách cập nhật ARP đó là thông qua ARP request và thông qua các gói IP đến. Mỗi khi có 1 gói IP đến, lẽ dĩ nhiên là gói này sẽ được giao thức IP xử lý, ARP không can thiệp vào quá trình xử lý đó. Tuy nhiên trong mỗi gói IP đến có 2 thông tin quan trọng mà ARP cần: đó là địa chỉ IP và địa chỉ MAC của host đã gửi gói tin đó. ARP sẽ dùng cặp địa chỉ này để cập nhật ARP cache.
                          Code:
                          //--------------------------------------------------------------------------------------
                          void arpIPPacketIn(unsigned char* ethFrame)
                          {
                          	struct ntEthHeader* ethHeader;
                          	struct ntIPHeader* ipHeader;
                          	ethHeader = (struct ntEthHeader*)ethFrame;
                          	ipHeader = (struct ntIPHeader*)(ethFrame + ETH_HEADER_LEN);
                          	arpUpdateEntry(ethHeader->srcAddr,HTONL(ipHeader->srcIPAddr));
                          }
                          //--------------------------------------------------------------------------------------
                          Cuối cùng là hàm phân giải địa chỉ để cung cấp địa chỉ MAC cho giao thức IP khi được yêu cầu
                          Code:
                          void arpIpOut(unsigned char* ethFrame, unsigned long phyDstIp)
                          {
                          	unsigned char index;
                          	struct ntEthHeader* ethHeader;
                          	struct ntIPHeader* ipHeader;
                          	ethHeader = (struct ntEthHeader*)ethFrame;
                          	ipHeader = (struct ntIPHeader*)(ethFrame + ETH_HEADER_LEN);
                          
                          	if(phyDstIp)
                          		index = arpSearchIP(phyDstIp);
                          	else
                          		index = arpSearchIP(HTONL(ipHeader->desIPAddr));
                          	if(index < ARP_TABLE_SIZE)
                          	{
                          		ethHeader->srcAddr  = ARPMyAddr.ethAddr;
                          		ethHeader->desAddr = ARPTable[index].ethAddr;
                          		ethHeader->type = HTONS(ETH_TYPE_IP);
                          	}
                          	else
                          	{
                          		ethHeader->srcAddr = ARPMyAddr.ethAddr;
                          		ethHeader->desAddr.addr[0] = 0xFF;
                          		ethHeader->desAddr.addr[1] = 0xFF;
                          		ethHeader->desAddr.addr[2] = 0xFF;
                          		ethHeader->desAddr.addr[3] = 0xFF;
                          		ethHeader->desAddr.addr[4] = 0xFF;
                          		ethHeader->desAddr.addr[5] = 0xFF;
                          		ethHeader->type = HTONS(ETH_TYPE_IP);
                          	}
                          	#ifdef ARP_DEBUG
                          	printf("ARP Result:");
                          	ipPrintAddr(ARPTable[index].ipAddr);printf("-");
                          	ethPrintAddr(&(ethHeader->desAddr));printf("\r\n");
                          	#endif
                          }
                          Trong hàm ArpIpOut trên, có 1 chỗ "lách luật", không tuân thủ đúng nguyên tắc làm việc của ARP, đố các bạn tìm ra, nếu có ai tìm ra mình sẽ giải thích tại sao lại làm như vậy.
                          Hàm kiểm tra timeout của các entry trong ARP cache. hàm này sẽ được gọi định kỳ bởi ngắt timer để kiểm tra xem có entry nào "quá date" hay không, và hủy các entry đó.
                          Code:
                          //--------------------------------------------------------------------------------------
                          void arpTimer(void)
                          //Goi moi 10s
                          {
                          	int index;
                          	for(index=0; index<ARP_TABLE_SIZE; index++)
                          	{
                          		if(ARPTable[index].time)
                          			ARPTable[index].time--;
                          	}
                          }
                          //--------------------------------------------------------------------------------------
                          Các hàm phục vụ cho mục đích debug:
                          Code:
                          #ifdef ARP_DEBUG
                          void arpPrintHeader(struct ntARPHeader* packet)
                          {
                          	printf("ARP Packet:\r\n");
                          	printf("Operation   : ");
                          	if(packet->opcode == HTONS(ARP_OPCODE_REQUEST))
                          		printf("REQUEST");
                          	else if(packet->opcode == HTONS(ARP_OPCODE_REPLY))
                          		printf("REPLY");
                          	else
                          		printf("UNKNOWN");
                          	printf("\n\r");
                          	printf("SrcHwAddr   : ");	ethPrintAddr(&packet->shwaddr);printf("\n\r");
                          	printf("SrcProtoAddr: ");	ipPrintAddr(HTONL(packet->sipaddr));printf("\n\r");
                          	printf("DstHwAddr   : ");	ethPrintAddr(&packet->dhwaddr);printf("\n\r");
                          	printf("DstProtoAddr: ");	ipPrintAddr(HTONL(packet->dipaddr));printf("\n\r");
                          }
                          //--------------------------------------------------------------------------------------
                          void arpPrintTable(void)
                          {
                          	unsigned char i;
                          
                          	// print ARP table
                          	printf("Time    Eth Address    IP Address\r\n");
                          	printf("---------------------------------------\r\n");
                          	for(i=0; i<ARP_TABLE_SIZE; i++)
                          	{
                          		printf("%d",(ARPTable[i].time));
                          		printf("   ");
                          		ethPrintAddr(&ARPTable[i].ethAddr);
                          		printf("  ");
                          		ipPrintAddr(ARPTable[i].ipAddr);
                          		printf("\n\r");
                          	}
                          }
                          #endif
                          //--------------------------------------------------------------------------------------
                          Sau khi viết hàm xong, nhớ thêm declare vào file header tương ứng nhé.

                          Đến đây là xong giao thức IP và ARP, trong phần này có gọi các hàm của giao thức TCP, UDP và ICMP mà ta vẫn chưa viết tới, nên dịch cũng sẽ bị báo lỗi thiếu 3 hàm này nhé.
                          Last edited by nttam79; 04-11-2011, 12:34. Lý do: Thêm giải thích cho code

                          Comment


                          • #28
                            Anh Tâm có thể share file nguyên lý orcad và layout lên luôn để anh em có thể ủi và bắt đầu ráp mạch được không. Nhìn cái hình anh upload lên mờ quá không thấy gì hết. Không biết còn bao nhiêu ngày nữa là đến phần kết anh nhỉ ?

                            Email:
                            Tel: 0983.497.310

                            Comment


                            • #29
                              Ai biết cách post flash lên diễn đàn xin chỉ dùm nhé, có mấy cái flash minh họa hoạt động của ethernet mà post thử hoài không được. Thanks

                              Comment


                              • #30
                                Nguyên văn bởi tienhuypro Xem bài viết
                                Anh Tâm có thể share file nguyên lý orcad và layout lên luôn để anh em có thể ủi và bắt đầu ráp mạch được không. Nhìn cái hình anh upload lên mờ quá không thấy gì hết. Không biết còn bao nhiêu ngày nữa là đến phần kết anh nhỉ ?
                                Thực ra mạch mà mình đã làm thì không chỉ có phần ethernet mà còn đủ thứ linh tinh khác nên phức tạp hơn nhiều so với sơ đồ mạch ở đầu. Và dùng linh kiện dán nên chắc không "ủi" được. Để mình tìm lại file layout và post lên. Post trước mấy hình nhé (tranh thủ quảng cáo tý):

                                Cận cảnh:

                                Gắn LCD:

                                Hệ thống menu trên LCD và keypad:



                                Chế độ command line qua Hyper Terminal:

                                Truy cập vào website:


                                Demo hoạt động của mạch luôn:


                                Không biết đến chừng nào xong nữa, vì mình chỉ tranh thủ thời gian rảnh post thôi, chắc cỡ 1 tuần
                                Last edited by nttam79; 04-11-2011, 13:08.

                                Comment

                                Về tác giả

                                Collapse

                                nttam79 Tìm hiểu thêm về nttam79

                                Bài viết mới nhất

                                Collapse

                                Đang tải...
                                X