Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Trang 1 của 3 123 CuốiCuối
Kết quả 1 đến 10 của 29
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    lỗi khó hiểu khi send dữ liệu qua mạng lan

    mình tạo ra 1 struct Message
    Mã nguồn PHP:
    struct Message { int messtype; char data[2048]; };  
    ví dụ của mình là client sẽ gủi cho server Message trên.

    mình dùng TCP để trao đổi dữ liệu

    client send 1 lần 1 message khi server nhận được message rồi thì báo lại cho client và client tự động send message tiếp theo(tiến hành 10 lần như vậy).


    có 1 vấn đề mình gặp phải là.


    trường hợp 1
    test trên cùng 1 máy(server sẽ lắng nghe trên cổng loopback của máy(127.0.0.1)) thì 10 message đều nhận đủ

    trường hợp 2
    test trên 2 máy khác nhau thì server nhận được 10 gói nhưng phần data[] không có dữ liệu

    trường hợp 3
    tiến hành debug quá trình gủi và nhận của trường hợp 2
    kết quả là nhận đủ 10 gói bao gồm cả phần data[]

    vậy lỗi trên do đâu mà ra.ai biết chỉ giúp mình

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Cho xem code cái đoạn nhận dữ liệu coi nào.
    Cái đoạn gọi hàm recv() ấy [IMG]images/smilies/smile.png[/IMG]

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    thank bạn.mình set data lại 1000 byte thì ok.mình nắm chưa chắc được quá trình send & recv hàm recv mình xin hỏi thêm vài câu nữa
    bạn có biết hàm recv() nhận tối đa trong 1 lần là bao nhiêu byte không?hay là nó nhận bất kì 1 giá trị nào đó (0-->vô cùng)?

    Giả sử mỗi lần bạn gửi đi là 2052 bytes mà ở ngay cái thời điểm bạn nhận về được có 100 bytes bạn cũng đem ra xử lý ngay à? --> Sai[/U][/U]

    vấn đề mình đang và rất thắc mắc ở chỗ này đây,nếu mình send khoảng 1000 byte mà nó nhận 50 byte thì mình thật sự chưa biết giải quyết thế nào.vì 1 ứng dụng có rất nhiều client và hàm recv() sẽ làm việc khi có sự kiện FD_READ nên rất khó để biết đâu là thông điêp của client nào

    mình ví dụ.

    2 client:client1client2.cùng send 1 lúc mỗi client 1 Message

    phía Server
    khi có sụ kiện FD_READ
    Server recv() nhận được 4 byte(giả sử lúc này là message của client1)
    -->chưa đủ 1 Message
    vậy Server recv() tiếp được 1000byte. hai lần nhận được 1004 byte
    -->đủ 1 Message
    nhưng 1000 byte nhận sau là của client2 thì sao?làm sao quản lý chỗ này

  4. #4
    Trích dẫn Gửi bởi rua_con
    thank bạn.mình set data lại 1000 byte thì ok.mình nắm chưa chắc được quá trình send & recv hàm recv mình xin hỏi thêm vài câu nữa
    bạn có biết hàm recv() nhận tối đa trong 1 lần là bao nhiêu byte không?hay là nó nhận bất kì 1 giá trị nào đó (0-->vô cùng)?
    Mình cũng chẳng biết nó nhận tối đa bao nhiêu nữa. Hehe!! nhưng nhận -1 (SOCKET_ERROR) thì tèo [IMG]images/smilies/smile.png[/IMG]


    vấn đề mình đang và rất thắc mắc ở chỗ này đây,nếu mình send khoảng 1000 byte mà nó nhận 50 byte thì mình thật sự chưa biết giải quyết thế nào.vì 1 ứng dụng có rất nhiều client và hàm recv() sẽ làm việc khi có sự kiện FD_READ nên rất khó để biết đâu là thông điêp của client nào

    mình ví dụ.

    2 client:client1client2.cùng send 1 lúc mỗi client 1 Message

    phía Server
    khi có sụ kiện FD_READ
    Server recv() nhận được 4 byte(giả sử lúc này là message của client1)
    -->chưa đủ 1 Message
    vậy Server recv() tiếp được 1000byte. hai lần nhận được 1004 byte
    -->đủ 1 Message
    nhưng 1000 byte nhận sau là của client2 thì sao?làm sao quản lý chỗ này
    Mỗi cái socket bạn dùng 1 buffer để nhận, khi gọi hàm recv thì ứng với socket nào bạn cho vào buffer tương ứng với buffer đó. Tất cả các socket nhận chung 1 buffer thì teo luôn.

    Muốn biết đủ hay chưa đủ bản tin thì đơn giản thôi.
    Mỗi buffer lại có 1 thông số là hiện đang lưu trữ bao nhiêu dữ liệu nhận được (remaining - khởi đầu chưa nhận thì cho remaining = 0)
    Tớ phác thảo thế này:



    Mã:
    unsigned char buffer[4096]  //buffer để nhận dữ liệu (của riêng mỗi socket)unsigned int  remaining = 0; //số bytes còn lại chưa xử lý trong buffervoid OnReceive(int nErrorCode){    int received = recv(sock,               /hận trên socket nào                        buffer + remaining, /hận dữ liệu bắt đầu từ vị trí remaining của buffer                        sizeof(buffer) - remaining, //số lượng bytes tối đa có thể nhận được vào buffer                        0);                 //    if(received > 0)        remaining += received; //cập nhật số byte chưa được xử lý trong buffer    unsigned char* buf = buffer;//lấy 1 biến tạm để xử lý dữ liệu    while(remaining >= sizeof(Message)) //khi nào số lượng byte dữ liệu chưa xử lý có kích cỡ lớn hơn 1 message    {        Message* msg = (Message *)buf;        //làm gì đó với cái message này        // ....        //Xử lý xong message rồi        buf += sizeof(Message);//chuyển đến đầu của message kế tiếp        remaining -= sizeof(Message); // cập nhật lại số lượng byte chưa xử lý           }    //dữ liệu còn dư lại không đủ 1 message    //cập nhật lại vùng lưu trữ dữ liệu    //Đưa vùng dữ liệu chưa xử lý về đầu buffer    memcpy(buffer, buf, remaining);}

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi namdq2k
    Cho xem code cái đoạn nhận dữ liệu coi nào.
    Cái đoạn gọi hàm recv() ấy [IMG]images/smilies/smile.png[/IMG]
    Mã:
    Phần nhận nó sẽ tương tự như vầy.bạn xem thử
    Mã nguồn PHP:
    recv(Server, (char*)&mess,GetSize(mess),0); /*sử lý dữ liệu nhận được*/ .............. /*báo lại cho client biết đã nhận được Message để client send tiếp*/ ..............  
    Mã nguồn PHP:
    /*hàm GetSize()*/ int GetSize(const Message &mess) { return(sizeof(mess.messtype) + sizeof(mess.data)); }  

  6. #6
    Ngày tham gia
    Sep 2015
    Đang ở
    Hà Nội
    Bài viết
    0
    <div class="bbcode_quote">
    <div class="quote_container">

    <div class="bbcode_postedby">
    [IMG]images/misc/quote_icon.png[/IMG] Nguyên bản được gửi bởi <strong>rua_con</strong>
    [IMG]images/buttons/viewpost-right.png[/IMG]

    <div class="message">
    Mã:
    Phần nhận nó sẽ tương tự như vầy.bạn xem thử
    Mã:
    int received = recv(SOCKET s, char* buff, int len, int flag);
    Thằng TCP không phải mỗi lần gửi đi bao nhiêu là khi nhận nó sẽ nhận bấy nhiêu. Nó chỉ đảm bảo nếu 2 socket kết nối thì nó sẽ truyền đầy đủ bản tin, nhưng không phải 1 lần nhận, có thể nhiều lần recv mới đủ bản tin.

    Hàm này trả về số byte nhận được. Giả sử mỗi lần bạn gửi đi là 2052 bytes mà ở ngay cái thời điểm bạn nhận về được có 100 bytes bạn cũng đem ra xử lý ngay à? --> Sai.

    Bạn phải có 1 cơ chế để biết rằng đã nhận đầy đủ 1 bản tin [IMG]images/smilies/smile.png[/IMG]

    3. Hàm getsize của bạn sao dài dòng thế?

    Mã:
    return sizeof(mess);
    là được

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    tuần vừa rồi bận quá nên không làm tiếp được
    nói chung thì mình send và nhận ok rồi nhưng mà theo như lý thuyết thì bài mình làm vẫn có thể bị lỗi[IMG]images/smilies/smile.png[/IMG]

    Mã:
    vì chỗ này vẫn có thể sảy ra lỗi
    Mã nguồn PHP:
    int received = recv(sock, /hận trên socket nào buffer + remaining, /hận dữ liệu bắt đầu từ vị trí remaining của buffer sizeof(buffer) - remaining, //số lượng bytes tối đa có thể nhận được vào buffer 0); //  
    giờ giả sử client1 send() cho server 2 Message,thì ở máy server buffer của hệ điều hành cấp cho chương trình có thể tồn tại trường hợp sau

    <div class="bbcode_description">HTML Code:
    50%Message1 ->50%Message2 ->50%Message1 ->50% Message2
    </div>vậy đoạn code trên sẽ nhận

    <div class="bbcode_description">HTML Code:
    Message1 = 50%Message1 + 50%Message2
    Message2 = 50%Message1 + 50%Message2
    </div>==>tiêu vậy trường hợp này không thể dựa vào socket nào để sét xem dữ liệu của client nào được rồi vì trường hợp này cùng 1 một client mà.không biết mình có lầm chỗ nào không bạn xem và góp ý dùm mình

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi rua_con
    giờ giả sử client1 send() cho server 2 Message,thì ở máy server buffer của hệ điều hành cấp cho chương trình có thể tồn tại trường hợp sau

    <div class="bbcode_description">HTML Code:
    <div class="bbcode_code" style="height:4*12px};">Message1 = 50%Message1 + 50%Message2
    Message2 = 50%Message1 + 50%Message2
    </div>==>tiêu vậy trường hợp này không thể dựa vào socket nào để sét xem dữ liệu của client nào được rồi vì trường hợp này cùng 1 một client mà.không biết mình có lầm chỗ nào không bạn xem và góp ý dùm mình</div>

    </div>
    </div>
    </div>Bạn đọc lại lý thuyết về TCP trước khi code đi. Làm gì có cái chuyện mạng ở dưới nó gửi lung tung như thế. Nó đảm bảo tính thứ tự của từng byte gửi đi.

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    mình đã đọc về tcp có lẽ mình hiểu sai đây là suy nghĩ của mình về tcp sai chỗ nào thì bạn nhắc dùm mình mình k sợ bị chửi ngu đâu

    mỗi Message của mình là 2000byte TCP dựa vào MTU để quyết định cắt Message của mình ra làm bao nhiêu gói giả sử trong trường hợp này nó cắt message làm 2 gói(mỗi gói 1000byte

    vậy khi client send 1 message thì chia làm 2 gói tin và send đi khi server nhận được gói tin thứ nhất nghĩa là 1000byte đầu tiên của Message1 thì phát sinh sự kiện FD_READ lúc đó server sẽ recv gói tin này?
    trong lúc client send message1 thì nó đồng thời send thêm 1 message2 giả sử gói tin thứ 2 của message1 gặp phải sự có nào đó chưa đến server được và server yêu cầu send lại.cũng trong lúc này gói tin thứ nhất của message2 đến và server phát sinh sự kiền FD_READ recv gói tin này ==>
    Mã:
    Message1 = 50%Message1 + 50%Message2
    Mã nguồn PHP:
    mình hiểu sai chỗ nào thì bạn nhắc dùm mình  
    theo như mình hiểu thì message2 vẫn có thể đến trước message1(TCP chỉ đảm bảo thứ tự của 1 khỗi dữ liệu chứ không đảm bảo thứ tự 2 khối dữ liệu khác nhau)

  10. #10
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    http://vi.wikipedia.org/wiki/TCP/IP
    TCP là một giao thức định hướng kết nối. Nó giải quyết nhiều vấn đề độ tin cậy để cung cấp một dòng byte đáng tin cậy (reliable byte stream):

    • Dữ liệu đến đích đúng thứ tự Sửa lỗi dữ liệu ở mức độ tối thiểu Dữ liệu trùng lặp bị loại bỏ Các gói tin bị thất lại/loại bỏ được gửi lại Có kiểm soát tắc nghẽn giao thông dữ liệu

 

 
Trang 1 của 3 123 CuốiCuối

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •