我有一個使用.Net遠程處理進行文件傳輸的大型應用程序。在某些情況下,插槽被強制關閉 - 這是因爲我沒有直接使用套接字,而是使用字節數組進行.Net遠程調用(我沒有在一次傳輸中發送整個文件,我正在分裂它)。使用套接字和多個客戶端進行文件傳輸
所以,我決定改變使用套接字實際的文件傳輸部分。
由於概念證明,看看我的原則吧,我寫了一個簡單的控制檯客戶端和服務器。
我使用ASYNCH臨危但同步寫 - 我試圖與這兩個是異步但同樣reseult,並保持同步國產調試更加方便。
什麼應用程序做(下面的代碼)是服務器坐着要傳輸的文件等待,它在給定的名字將它們存儲在目錄中。
當進入被按下,然後服務器讀取收到這些文件,並將它們發送回誰把它們存儲在不同的名稱的客戶端。我想以兩種方式測試文件傳輸。
使用的客戶端應用程序的一個實例,一切都很好 - 服務器臨危它,然後將其發送回客戶端。一切都很好。是的,當你終止服務器時,客戶端會拋出異常 - 但這很好 - 我知道套接字被強行關閉了......我可以在代碼正常工作時處理這些代碼。但是,當我創建客戶端代碼的2個實例(不要忘記稍微修改代碼以讀取要發送的不同文件,並且以不同名稱存儲接收到的文件)時,服務器將從以下位置接收這兩個文件:客戶端,發送第一個回來就好了,然後幾個段到第二個文件拋出與「非阻塞套接字操作無法立即完成」 - 這很奇怪,因爲沒有阻塞,並且收件人是異步 - 而發送實際上是阻止!
任何建議,請給我在做什麼錯了 - 毫無疑問,這是愚蠢的東西,但仍...
最終代碼的目的是爲了能夠有N個客戶端與服務器聯繫併發送文件,並且隨機服務器會將一個或多個文件發送回某些/所有客戶端。
乾杯人!
Server代碼
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace SocketServer
{
class ConnectionInfo
{
public Socket Socket;
public byte[] Buffer;
public int client;
}
class Program
{
static int chunkSize = 16 * 1024;
static int chucksizeWithoutHeaderData = chunkSize - 8;
static List<ConnectionInfo> list = new List<ConnectionInfo>();
static Socket serverSocket;
static int nClient = 0;
static void AcceptCallback(IAsyncResult result)
{
ConnectionInfo info = new ConnectionInfo();
info.Socket = serverSocket.EndAccept(result);
info.Buffer = new byte[chunkSize];
Console.WriteLine("Client connected");
nClient++;
info.client = nClient;
list.Add(info);
info.Socket.BeginReceive(info.Buffer,0,info.Buffer.Length,SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback),null);
}
static void ReceiveCallBack(IAsyncResult result)
{
ConnectionInfo info = result.AsyncState as ConnectionInfo;
try
{
Int32 nSegmentNumber = BitConverter.ToInt32(info.Buffer,0);
Int32 nMaxSegment = BitConverter.ToInt32(info.Buffer,4);
string strFileName = string.Format(@"c:\temp\from-client-{0}.dat",info.client);
int bySize = info.Socket.EndReceive(result);
using (FileStream fs = new FileStream(strFileName, FileMode.OpenOrCreate))
{
Console.WriteLine("Received segment {0} of {1} from client {2}", nSegmentNumber, nMaxSegment, info.client);
fs.Position = fs.Length;
fs.Write(info.Buffer, 8, bySize-8);
if (nSegmentNumber >= nMaxSegment)
{
Console.WriteLine("Completed receipt from client {0}", info.client);
}
}
info.Socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static void Main(string[] args)
{
try
{
Console.WriteLine("Server");
IPAddress address = IPAddress.Parse("127.0.0.1"); //The IP address of the server
IPEndPoint myEndPoint = new IPEndPoint(address, 6503);
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(myEndPoint);
serverSocket.Listen(1000);
for (int n = 0; n < 10; ++n)
{
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
Console.WriteLine("Server now waiting");
Console.ReadLine();
foreach (ConnectionInfo info in list)
{
string strFileName = string.Format(@"c:\temp\from-client-{0}.dat", info.client);
using (FileStream fs = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
int nMaxChunk = 0;
int nCurrentChunk = 0;
nMaxChunk = (int)(fs.Length/chucksizeWithoutHeaderData);
if ((nMaxChunk * chucksizeWithoutHeaderData) < fs.Length)
{
++nMaxChunk;
}
using (BinaryReader br = new BinaryReader(fs))
{
byte[] byBuffer;
Int64 nAmount = 0;
byte[] byMaxChunk = BitConverter.GetBytes(nMaxChunk);
while (fs.Length > nAmount)
{
++nCurrentChunk;
byte[] byCurrentChunk = BitConverter.GetBytes(nCurrentChunk);
byBuffer = br.ReadBytes(chucksizeWithoutHeaderData);
Console.WriteLine("Sending {0}bytes, chunk {1} of {2} to client {3}", byBuffer.Length,nCurrentChunk,nMaxChunk, info.client);
byte [] byTransmitBuffer = new byte[byBuffer.Length + 8];
Array.Copy(byCurrentChunk, byTransmitBuffer, 4);
Array.Copy(byMaxChunk, 0,byTransmitBuffer, 4, 4);
Array.Copy(byBuffer, 0, byTransmitBuffer, 8, byBuffer.Length);
info.Socket.Send(byTransmitBuffer);
nAmount += byBuffer.Length;
}
}
}
}
Console.WriteLine("Press enter to end server");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
}
}
}
}
客戶端代碼
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace SocketClient
{
class Program
{
static TcpClient socket = new TcpClient();
static int chunkSize = 16 * 1024;
static int chucksizeWithoutHeaderData = chunkSize - 8;
static byte[] byReceiveBuffer = new byte[chunkSize];
static void ReceiveCallBack(IAsyncResult result)
{
Socket socket = result.AsyncState as Socket;
try
{
int bySize = socket.EndReceive(result);
Console.WriteLine("Recieved bytes {0}", bySize);
if (bySize != 0)
{
Int32 nSegmentNumber = BitConverter.ToInt32(byReceiveBuffer, 0);
Int32 nMaxSegment = BitConverter.ToInt32(byReceiveBuffer, 4);
Console.WriteLine("Received segment {0} of {1}", nSegmentNumber, nMaxSegment);
string strFileName = string.Format(@"c:\temp\client-from-server.dat");
using (FileStream fs = new FileStream(strFileName, FileMode.OpenOrCreate))
{
fs.Position = fs.Length;
fs.Write(byReceiveBuffer, 8, bySize-8);
}
if (nSegmentNumber >= nMaxSegment)
{
Console.WriteLine("all done");
}
}
socket.BeginReceive(byReceiveBuffer, 0, byReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static void Main(string[] args)
{
Console.WriteLine("Press enter to go");
Console.ReadLine();
socket.Connect("127.0.0.1", 6503);
Console.WriteLine("Client");
Console.ReadLine();
byte[] byBuffer;
socket.Client.BeginReceive(byReceiveBuffer, 0, byReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket.Client);
using (FileStream fs = new FileStream(@"c:\temp\filetosend.jpg", FileMode.Open, FileAccess.Read, FileShare.None))
{
using (BinaryReader br = new BinaryReader(fs))
{
int nMaxChunk = 0;
int nCurrentChunk = 0;
nMaxChunk = (int)(fs.Length/chucksizeWithoutHeaderData);
if ((nMaxChunk * chucksizeWithoutHeaderData) < fs.Length)
{
++nMaxChunk;
}
byte[] byMaxChunk = BitConverter.GetBytes(nMaxChunk);
Int64 nAmount = 0;
while (fs.Length > nAmount)
{
++nCurrentChunk;
byte[] byCurrentChunk = BitConverter.GetBytes(nCurrentChunk);
byBuffer = br.ReadBytes(chucksizeWithoutHeaderData);
Console.WriteLine("Sending {0}bytes, chunk {1} of {2}", byBuffer.Length, nCurrentChunk, nMaxChunk);
byte[] byTransmitBuffer = new byte[byBuffer.Length + 8];
Array.Copy(byCurrentChunk, byTransmitBuffer, 4);
Array.Copy(byMaxChunk, 0, byTransmitBuffer, 4, 4);
Array.Copy(byBuffer, 0, byTransmitBuffer, 8, byBuffer.Length);
socket.Client.Send(byTransmitBuffer);
nAmount += byBuffer.Length;
}
}
}
Console.WriteLine("done");
Console.ReadLine();
}
}
}
嗨,謝謝你的建議。但這不是一個選項 - 這需要一個獨立的服務,只需一個安裝程序。當我說「這個」時,我的意思是這是一個PoC的程序。有關上述代碼可能出錯的任何建議? – Manicguitarist 2011-03-24 18:58:29
也 - 也需要在所有的客戶端上安裝FTP服務器....並要求戳穿防火牆漏洞......以及缺少加密和...並且... – Manicguitarist 2011-03-24 20:01:39