C#app如何轻松地在网络上传输和传输文件?

问题描述 投票:6回答:4

C#app如何轻松地与位于同一网络上的另一台计算机上的自身实例进行通信,并传输文件和数据?

假设网络上的计算机具有固定的本地IP地址,并且每个计算机都知道彼此的IP。如果IP未知,是否还有通信方式?基于一些发现协议?

我听说Apple的“Bonjour”服务是一个很好的协议。我们可以通过Windows应用程序进行通信吗?或者你必须使用“套接字”。我主要是在寻找可以轻松满足我需求的库或示例代码,我不想开发自己的基于TCP的协议或任何硬核!

c# networking communication data-transfer file-transfer
4个回答
2
投票

对于传输文件/数据,您可以使用TcpClient / TcpListener类,这是对grittier套接字功能的很好的抽象。或者,您可以使用HttpListener类将应用程序简单地作为HTTP服务器,如果这对您的应用程序更容易/更适合。

对于发现,如果您能够拥有中央服务器;那么你可以让每个客户端在启动时连接到服务器,注册自己并检索其他在线客户端及其IP的列表。然后可以在客户端之间直接进行后续通信。

这种方案的一个变体是让中央服务器充当代理,客户端之间的所有流量都流过。如果客户端不在同一网络上,那么这对克服防火墙或路由问题大多有帮助(因此,您的方案可能不需要它)。


5
投票

您可以使用System.Net.Sockets类进行通信,它有一个发送文件Socket.SendFile的方法。

更新: 这是file sharing and sending file from C# help的一个很好的例子


3
投票

C#中文件和套接字的优点在于它们都作为流公开。将大文件从一个流复制到另一个流非常简单:

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

然后在完成后关闭套接字。

如果要发送元数据(文件名,大小)或不想关闭连接,则需要某种协议来处理此问题。 FTP使用两个单独的套接字(一个用于元数据,一个用于数据;这称为带外通信)。如果你在没有防火墙的局域网上,这是完全可以接受的。另一方面,如果你想进行互联网转移,打开一个端口是一项艰巨的任务,而且两个是无法忍受的。如果您不太关心性能,可以使用base64编码对字节进行编码,这样可以确保它们在某个字节范围内。使用base64,您可以使用换行符或其他非字母数字字符分隔邮件。然后在第一个消息中包括文件名,大小或其他,然后将数据作为第二个消息发送,然后发送“这是整个文件”消息,以便客户端知道它已完成。

消息的另一种策略是使用转义序列。例如,取你的字节流并用'\ 0 \ 0'替换'\ 0'的每个实例。现在使用'\ 0 \ 1'来表示消息结束,这保证不会包含在您的数据消息中。在接收端将'\ 0 \ 0'解码回'\ 0'。这在C中运行良好,但我发现,实际上,循环遍历每个字节可能比读取C#中的整个缓冲区要慢。

最好的方法是采用某种自适应长度协议。例如,以一定大小(例如512字节)的块发送数据。在每个块之前,通过System.BitConverter发送一个表示块大小的32位int。所以消息看起来像这样(英语):

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

这里的优点是您可以使复制/读取缓冲区为您工作(一次读取512个字节),这意味着您的吞吐量受到网络堆栈而不是C#代码的限制。客户端读取固定长度的32位int,让它知道它应该用于下一个[data]段的缓冲区大小。

这里有一些代码来编写这样的消息:

        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();

这里有一些代码来阅读它们:

               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;

1
投票

要复制文件,您可能还需要查看属于Microsoft Sync Framework的文件同步提供程序。 http://msdn.microsoft.com/en-us/sync/bb887623

© www.soinside.com 2019 - 2024. All rights reserved.