2009-04-15 33 views
5

Tôi đang cố gắng sử dụng một số lập trình mạng ổ cắm trong C++. Tôi đang cố gửi tin nhắn "Hello World!" đến một máy chủ bằng cách sử dụng hàm C++ send(). Lúc đầu, tôi đặt bộ đệm với kích thước 13 từ "Hello World!" hoàn toàn là 12 ký tự (bạn phải làm cho nó nhiều hơn số ký tự). Chức năng gửi chỉ gửi các ký tự đến máy chủ nếu tôi gửi nó khoảng 7 lần. Và khi nó cuối cùng đến máy chủ, nó trông giống như sau:Ổ C++ socket 256 byte

"Xin chào thế giới! Hello World! Xin chào thế giới! Hello World! Xin chào thế giới! Hello World! Xin chào thế giới!"

Bây giờ, đây là phần thú vị. "Hello World!" câu sẽ gửi ngay lập tức nếu tôi đặt kích thước bộ đệm là 256 (bộ đệm char [256];). Khi nói đến máy chủ như vậy, nó cho thấy "Hello World!" với một bó toàn bộ không gian sau hai từ. Tại sao điều này xảy ra và nếu có thể, làm thế nào tôi có thể sửa nó? Làm ơn cho tôi biết.

Cảm ơn

+0

Bạn đã vô hiệu hóa chuỗi của mình chưa? "Hello World! \ 0" – Alan

Trả lời

7

Khi bạn gọi read (hoặc receive) với đệm của bạn để đọc từ ổ cắm, một giá trị số nguyên được trả về mà xác định số byte đọc. Bạn chỉ nên lấy nhiều từ bộ đệm. Phần còn lại không liên quan:

int count = read(...); 
// buffer[0 .. count - 1] contains the appropriate data. 
+0

Và chỉ để cho bạn biết, máy chủ nhận dữ liệu được thực hiện trong C# – QAH

+0

QAH: Điều này cũng đúng đối với các ổ cắm C#, phương pháp Socket.Receive. –

4

Bộ đệm tồn tại để lưu trữ dữ liệu cho đến khi bạn sẵn sàng gửi. Bạn có kích thước bộ đệm gửi là 256. Cho đến khi 256 ký tự được truyền qua bộ đệm, dữ liệu của bạn sẽ không được gửi sang phía bên kia. Bạn có thể sửa lỗi này bằng cách gọi phương thức xả trên bộ đệm khi bạn biết bạn đã sẵn sàng gửi.

Để rõ ràng, bạn đang lưu vào bộ đệm trong nội bộ, sau đó hệ điều hành (hoặc thư viện) đang lưu vào bộ đệm một lần nữa khi bạn gọi send() và truyền một số dữ liệu.

Nếu bạn cụ thể hơn với thư viện bạn đang sử dụng và có thể bao gồm đoạn mã, chúng tôi có thể tìm thấy hàm đệm phù hợp để gửi cho bạn theo cách của bạn.

Hoặc, nếu bạn đang ở trong * nix, chỉ cần tắt thuật toán của Nagle để hệ điều hành sẽ không đệm các gói nhỏ của bạn. Hoặc, khi bạn thiết lập ổ cắm, hãy đảm bảo sử dụng tùy chọn TCP_NODELAY

6

Thuật toán của Nagle thường được bật theo mặc định. Điều này sẽ kết hợp một số gói nhỏ thành một. Tắt thuật toán của Nagle sẽ cho phép gửi các gói nhỏ ngay lập tức.

0

Giả sử đây là ổ cắm SOCK_STREAM, điều quan trọng cần lưu ý là giao thức TCP cơ bản không duy trì bất kỳ ranh giới phân đoạn nào. Tức là, khi bạn gọi send() nhiều lần, tất cả dữ liệu bạn đã gửi có thể dễ dàng được trả về bằng một cuộc gọi recv() duy nhất ở đầu kia. Hoặc, dữ liệu được gửi trong một cuộc gọi send() có thể được trả lại trong nhiều recv() s ở đầu bên kia, ví dụ: nếu một số gói bị trễ do tắc nghẽn mạng. Đây là nền tảng cho thiết kế của TCP và ứng dụng của bạn phải được thiết kế phù hợp.

Ngoài ra, như được chú thích bởi Mehrdad, lệnh gọi recv() trả về số byte đã đọc ra khỏi dây. Bất cứ điều gì sau thời điểm đó trong bộ đệm là rác, và dữ liệu không phải là zero-chấm dứt.

Ổ cắm SOCK_DGRAM sử dụng UDP bên dưới, hoàn toàn theo định hướng gói, ngược lại với hướng luồng như TCP. Tuy nhiên, UDP không đảm bảo độ tin cậy (U là viết tắt của Unreliable), vì vậy bạn phải xử lý các gói bị mất, bị sao chép, không theo thứ tự vv. Điều này khó hơn rất nhiều so với định hướng luồng I/O.

+0

UDP là Giao thức Datagram của Người dùng - nó không có gì đáng tin cậy về tên của nó. Bạn đúng là nó tương đối không đáng tin cậy, mặc dù :) –

0

Lập trình socket quá tẻ nhạt, dễ bị lỗi và không di động.Bắt đầu sử dụng các thư viện như Boost hoặc ACE để bảo vệ bạn khỏi API C cấp thấp và cung cấp cho bạn tóm tắt độc lập nền tảng.

Các vấn đề liên quan