您的位置:首页 > 理论基础 > 计算机网络

C#通过Socket进行网络传输文件

2012-06-13 10:57 537 查看
转贴:

如果想要利用C#通过Socket进行网络传输文件,一般情况下,大家会首先考虑使用.NET自带的 Socket.SendFile Method (String)这个方法。不过这个方法没有相应的文件接受方法,而且据说会有8KB的限制。所以,我尝试了另外一种方法,发现效果不错。下面,我就来简 单介绍一下其原理。
  Socket.Send()和Socket.Receive()方法都是传递byte[]的,所以就要想办法把文件给变成 byte[]。一开始试过用StreamReader来读取string,然后用Encoding来进行编码得到byte[],接收以后再还原成 string写入文件。结果发现不可行,只有纯文本文件以这种方法传输是正常的。
  无奈之下,只好另想办法。后来在File类下找到了这两个方 法——File.ReadAllBytes()和File.WriteAllBytes()。试了一下用这两个方法来把文件变成byte[],再把 byte[]还原成文件,结果成功了!(试过了传输图片和rar压缩文件,都OK!)

C# code
/**************************************************
* Class Name:  MyRenFramework.NetWork.SynchronousSocket
* Description: The socket does socket communication
*              in the Synchronous way.
*              It is better used as a server socket.
* Create By:   Steven Mo
* Version:     2008-01
**************************************************/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace MyRenFramework.NetWork
{
///  <summary>
/// SynchronousSocket
///  </summary>
public class SynchronousSocket
{
private const int BUFFER_SIZE = 65536;
private const int CONNECTED_WAITTIME = 50;

private const string END_OF_STRING = "$EOS$";
private const int LISTEN_BACKLOG = 100;
private IPEndPoint _localEndPoint;
private IPAddress _localIpAddress;
private IPEndPoint _remoteEndPoint;
public delegate void AcceptedFileSavedEventHandler(string fileName);

public delegate void SocketConnectedEventHandler(Socket connectedSocket);

public delegate void StringReceivedEventHandler(Socket connectedSocket, string receivedData);
public delegate void StringSentEventHandler(Socket connectedSocket, int sentBytes);
public event SocketConnectedEventHandler SocketConnected;
public event StringReceivedEventHandler StringReceived;
public event StringSentEventHandler StringSent;
public event AcceptedFileSavedEventHandler AcceptedFileSaved;

public SynchronousSocket()
{
_localIpAddress = IP.GetLocalIP();
}
public void StartListening(int localPort)
{
try
{
_localEndPoint = new IPEndPoint(_localIpAddress, localPort);

// Create a TCP/IP listener.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

listener.Bind(_localEndPoint);
listener.Listen(LISTEN_BACKLOG);

while (true)
{
Socket connectedSocket = listener.Accept();

// Wait for the connection to be stabilized.
Thread.Sleep(CONNECTED_WAITTIME);

// Call the SocketConnected event.
SocketConnected(connectedSocket);
}
}
catch
{
return;
}
}
public void StartConnecting(string remoteHostNameOrAddress, int remotePort)
{
try
{
IPAddress ipAddress = IP.GetRemoteIpAddress(remoteHostNameOrAddress);
_remoteEndPoint = new IPEndPoint(ipAddress, remotePort);

// Create a TCP/IP client.
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

// Connect to the remote endpoint.
client.Connect(_remoteEndPoint);

// Wait for the connection to be stabilized.
Thread.Sleep(CONNECTED_WAITTIME);

// Call the SocketConnected event.
SocketConnected(client);
}
catch
{
return;
}
}

private int SendBytes(Socket connectedSocket, byte[] bytes)
{
int bytesSent = 0;
while (bytesSent  < bytes.Length)
{
int size;
if (bytes.Length - bytesSent >= BUFFER_SIZE)
{
size = BUFFER_SIZE;
}
else
{
size = bytes.Length - bytesSent;
}
bytesSent += connectedSocket.Send(bytes, bytesSent, size, SocketFlags.None);
Thread.Sleep(10);
}
Thread.Sleep(1000);
return bytesSent;
}
public void SendData(Socket connectedSocket, String data)
{
try
{
// Convert the string data to byte data using Unicode encoding.
byte[] byteData = Encoding.Unicode.GetBytes(data + END_OF_STRING);

// Begin sending the data to the remote device.
int bytesSent = SendBytes(connectedSocket, byteData);

// Call the StringSent event.
StringSent(connectedSocket, bytesSent - END_OF_STRING.Length);
}
catch
{
return;
}
}
public void TransmitFile(Socket connectedSocket, string fileName)
{
try
{
byte[] fileData = File.ReadAllBytes(fileName);
int fileSize = fileData.Length;
byte[] byteSize = Encoding.Unicode.GetBytes(fileSize + END_OF_STRING);

// Send the size of the byte array.
connectedSocket.Send(byteSize, 0, byteSize.Length, SocketFlags.None);

// Send the data of the file.
SendBytes(connectedSocket, fileData);
}
catch
{
return;
}
}
public void AcceptFile(Socket connectedSocket, string fileName)
{
try
{
byte[] bytes = new Byte[BUFFER_SIZE];
byte[] fileData;
int fileSize;
int receivedBytes = 0;

// Receive the size of the byte array.
while (true)
{
String receivedData = string.Empty;
int bytesRec = connectedSocket.Receive(bytes);
receivedData += Encoding.Unicode.GetString(bytes, 0, bytesRec);
if (receivedData.IndexOf(END_OF_STRING) > -1)
{
receivedData = receivedData.Replace(END_OF_STRING, string.Empty);
fileSize = Convert.ToInt32(receivedData);
fileData = new byte[fileSize];
break;
}
}

// Receive the data of the file.
while (receivedBytes  < fileSize)
{
int bytesRec = connectedSocket.Receive(bytes);
if (bytesRec  < BUFFER_SIZE)
{
for (int i = receivedBytes, j = 0; i  < fileSize && j  < bytesRec; i++, j++)
{
fileData[i] = bytes[j];
}
}
else
{
bytes.CopyTo(fileData, receivedBytes);
}
receivedBytes += bytesRec;
}

// Save file.
File.WriteAllBytes(fileName, fileData);

// Call the AcceptedFileSaved event.
AcceptedFileSaved(fileName);
}
catch
{
return;
}
}
public void ReceiveData(Socket connectedSocket)
{
try
{
String receivedData = string.Empty;
byte[] bytes = new Byte[BUFFER_SIZE];

while (true)
{
int bytesRec = connectedSocket.Receive(bytes);
receivedData += Encoding.Unicode.GetString(bytes, 0, bytesRec);
if (receivedData.IndexOf(END_OF_STRING) > -1)
{
// Call the StringReceived event.
receivedData = receivedData.Replace(END_OF_STRING, string.Empty);
StringReceived(connectedSocket, receivedData);
break;
}
}
}
catch
{
return;
}
}

#endregion
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: