2009-08-09 31 views
6

Làm thế nào để một ứng dụng C# có thể dễ dàng giao tiếp với một cá thể hiện diện trên một máy tính khác, trên cùng một mạng, và chuyển các tập tin và dữ liệu?Làm cách nào để ứng dụng C# có thể dễ dàng giao tiếp và chuyển các tệp trên mạng?

Giả sử các máy tính trên mạng có các địa chỉ IP cục bộ cố định và mỗi địa chỉ IP đều biết nhau. Liệu có cách nào để giao tiếp nếu các IP không được biết? dựa trên một số giao thức khám phá?

Tôi nghe dịch vụ "Bonjour" của Apple là một giao thức tốt. Chúng ta có thể giao tiếp thông qua ứng dụng Windows của mình không? Hay bạn phải sử dụng "ổ cắm". Tôi chủ yếu tìm kiếm các thư viện hoặc mã mẫu có thể đáp ứng nhu cầu của tôi một cách dễ dàng, tôi không muốn phát triển giao thức dựa trên TCP của riêng tôi hay bất kỳ thứ gì khác!

Trả lời

2

Để truyền tệp/dữ liệu, bạn có thể sử dụng các lớp học TcpClient/TcpListener, đây là tóm tắt tốt đẹp về chức năng ổ cắm grittier. Hoặc, bạn có thể chỉ đơn giản là có ứng dụng như một máy chủ HTTP bằng cách sử dụng lớp HttpListener, nếu đó là dễ dàng hơn/nhiều hơn thích hợp cho ứng dụng của bạn.

Để khám phá, nếu bạn có thể có máy chủ trung tâm; sau đó bạn có thể có mỗi khách hàng kết nối với máy chủ lúc khởi động, để đăng ký chính nó và lấy một danh sách các khách hàng trực tuyến khác và IP của họ. Giao tiếp tiếp theo sau đó có thể diễn ra trực tiếp giữa các khách hàng.

Một biến thể của lược đồ này, là để cho máy chủ trung tâm hoạt động như một proxy, tất cả lưu lượng truy cập giữa các máy khách đều được truyền qua. Điều này sẽ hữu ích nhất để khắc phục các vấn đề về tường lửa hoặc định tuyến nếu các máy khách không nằm trên cùng một mạng (vì vậy nó không cần thiết cho kịch bản của bạn).

+0

Các lớp ASP.Net? Tôi đang tìm kiếm sự tương tác giữa các ứng dụng Windows. –

+0

Ý bạn là gì? Không có lớp nào tôi đề cập đến là các lớp ASP .NET. – driis

2

Những điều tuyệt vời về các tập tin và ổ cắm trong C# là họ đang cả hai tiếp xúc như suối. Sao chép tệp lớn từ luồng này sang luồng khác khá đơn giản:

byte[] data = new byte[1024]; 
while(true) { 
int bytesRead = filestream.read(data,0,data.Length); 
if (bytesRead==0) break; 
netstream.write(data,0,bytesRead); 
} 

Sau đó, chỉ cần đóng ổ cắm khi bạn hoàn tất.

Nếu bạn muốn gửi siêu dữ liệu (tên tệp, kích thước) hoặc không muốn đóng kết nối, bạn cần một số loại giao thức để xử lý việc này. FTP sử dụng hai ổ cắm riêng biệt (một cho siêu dữ liệu, một cho dữ liệu; điều này được gọi là truyền thông ngoài băng thông). Nếu bạn đang ở trên mạng LAN không có tường lửa, điều đó có thể được chấp nhận hoàn toàn. Mặt khác, nếu bạn muốn thực hiện chuyển giao internet, việc mở một cổng duy nhất là một nhiệm vụ khó khăn và cả hai đều không thể chịu nổi. Nếu bạn không quan tâm quá nhiều về hiệu suất, bạn có thể mã hóa các byte trong mã hóa base64, điều này đảm bảo rằng chúng nằm trong một phạm vi byte nhất định. Với base64, bạn có thể tách riêng các thư với dòng mới hoặc các ký tự không phải chữ và số khác. Sau đó, trong tin nhắn đầu tiên bao gồm tên tệp, kích thước hoặc bất kỳ thứ gì, sau đó gửi dữ liệu dưới dạng tin nhắn thứ hai, sau đó gửi thông báo "đó là toàn bộ tệp" để khách hàng biết nó đã hoàn tất.

Một chiến thuật khác cho các thư đang sử dụng chuỗi thoát. Ví dụ, lấy bytestream của bạn và thay thế mỗi instance của '\ 0' bằng '\ 0 \ 0'. Bây giờ sử dụng '\ 0 \ 1' để báo hiệu phần cuối của tin nhắn, được đảm bảo không được chứa trong thông điệp dữ liệu của bạn. Giải mã '\ 0 \ 0' quay lại '\ 0' trên đầu nhận.Điều này hoạt động tốt trong C, nhưng tôi thấy rằng, trong thực tế, lặp qua từng byte có thể chậm hơn so với việc đọc toàn bộ bộ đệm trong C#.

Cách tốt nhất là áp dụng một số loại giao thức có chiều dài thích ứng. Ví dụ, gửi dữ liệu trong các khối của một kích thước nhất định (nói 512 byte). Trước mỗi đoạn, gửi một 32 bit int đại diện cho kích thước của đoạn thông qua System.BitConverter. Vì vậy, thông điệp giống như thế này (tiếng Anh):

Here's 512 bytes: 
[data] 
Here's 512 bytes: 
[data] 
Here's 32 bytes: 
[data] 
Here's 4 bytes: 
That was the whole file 

Ưu điểm ở đây là bạn có thể làm cho sao chép/đọc bộ đệm làm việc cho bạn (đọc 512 byte tại một thời điểm), có nghĩa là thông lượng của bạn bị hạn chế bởi ngăn xếp mạng của bạn thay vì mã C# của bạn. Máy khách đọc int 32-bit có độ dài cố định cho phép nó biết kích thước của bộ đệm mà nó sẽ sử dụng cho phân đoạn [dữ liệu] tiếp theo.

Dưới đây là một số mã để viết tin nhắn như thế:

 logger.logger.debug("Sending message of length " + length); 
     byte[] clength = System.BitConverter.GetBytes(buffer.Length); 
     plaintextStream.Write(clength,0,clength.Length); 
     plaintextStream.Write(buffer,0,buffer.Length); 
     plaintextStream.Flush(); 

Và đây là một số mã để đọc chúng:

   byte[] intbuf = new byte[int_32_size]; 
     int offset = 0; 
     while (offset < int_32_size) 
     { 
      int read = 0; 

      read = d.plaintextStream.Read(intbuf,offset,int_32_size - offset); 
      offset += read; 

     } 
     int msg_size = System.BitConverter.ToInt32(intbuf,0); 
     //allocate a new buffer to fill the message 
     byte[] msg_buffer = new byte[msg_size]; 
     offset = 0; 
     while (offset < msg_size) 
     { 
      int read = 0; 

      read = d.plaintextStream.Read(msg_buffer,offset,msg_size - offset); 
      offset += read; 
     } 


     return msg_buffer; 
Các vấn đề liên quan