我必須開發一個簡單的TCP文件傳輸客戶端作爲練習/演示的一部分,但我在數據傳輸方面遇到了問題。使用TCP文件傳輸客戶端發送時遇到問題
我已經提供了TCP文件服務器,它將接收傳入的文件,我必須編寫一個客戶端,它將連接併發送文件到服務器。到目前爲止,我已經成功地將所選文件的數據轉換爲準備好傳輸併成功打開連接然後發送數據的格式,但是即使在接收的服務器上遇到問題 - 我也不允許更改服務器的代碼,並因此應該更改我的客戶端代碼,以便發送的數據可以由服務器解釋。下面是我使用的代碼(有些被冷落是簡單的開銷,比如輸入框獲取IP地址等):
鏈接,TCP服務器與解決方案(如果你喜歡):https://www.mediafire.com/?682owf9wtdzmxac
TCP文件傳輸客戶端發送方法:
private void TransferFile(string _sFileName, string _sIPAdress)
{
//Convert data for transfer
Stream strmfilestream = File.OpenRead(_sFileName);
Byte[] bFileBuffer = new Byte[strmfilestream.Length];
//Open TCP/IP Connection
TcpClient tcpClientSocket = new TcpClient(_sIPAdress,8080);
NetworkStream nsNetworkStream = tcpClientSocket.GetStream();
nsNetworkStream.Write(bFileBuffer,0,bFileBuffer.GetLength(0));
nsNetworkStream.Close();
}
*注:_sFileName是剛剛從打開文件對話框完整的文件路徑+文件名。
這裏是服務器的負載方法得到的東西去:
if (!Directory.Exists(@"C:\TCPFileServer"))
Directory.CreateDirectory(@"C:\TCPFileServer");
//Get Ip address of server host machine
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
lblServerIP.Text = IPHost.AddressList[5].ToString();
lstSockets = new ArrayList();
Thread thdListener = new Thread(new ThreadStart(listenerThread));
thdListener.IsBackground = true; //This will enabe the thread to terminate when application is closed
thdListener.Start();
這裏是監聽線程方法:
public void listenerThread()
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 8080);
tcpListener.Start();
while (true)
{
Socket handlerSocket = tcpListener.AcceptSocket();
if (handlerSocket.Connected)
{
this.Invoke((Action)(() => lstConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.")));
lock (this)
{
lstSockets.Add(handlerSocket);
}
ThreadStart thdsHandler = new ThreadStart(handlerThread);
Thread thdHandler = new Thread(thdsHandler);
thdHandler.Start();
}
}
}
然後lasty這裏的處理器線程方法:
public void handlerThread()
{
try
{
int iBlockSize = 1024 * 3000; //3mb block size
Byte[] dataByte = new Byte[iBlockSize];
Byte[] rcvdData = new Byte[128000 * 1024];//128mb File Limit
Socket handlerSocket = (Socket)lstSockets[lstSockets.Count - 1];
NetworkStream networkStream = new NetworkStream(handlerSocket);
int i = 0;
int iRcvdBytes = 0;
while (true)
{
//Read from socket and store to buffer 'dataByte'
iRcvdBytes = networkStream.Read(dataByte, 0, iBlockSize);
dataByte.CopyTo(rcvdData, i);//Copy recieved bytes,from buffer, to another byte array
i += iRcvdBytes;
if (iRcvdBytes == 0) break;
}
//Get the File name length, BitConvertor occupies the first 4 bytes
int iFileNameLength = BitConverter.ToInt32(rcvdData, 0);
//Get the file name using length as the size and 4 as the offset
string sFileName = Encoding.ASCII.GetString(rcvdData, 4, iFileNameLength);
Stream fileStream = File.Open("C:\\TCPFileServer\\" + sFileName, FileMode.Create);
//Populate raw File on local machine
fileStream.Write(rcvdData, 4 + iFileNameLength, i - 4 - iFileNameLength);
fileStream.Close();
//Update BRS Net Files Server Log
this.Invoke((Action)(() => lstConnections.Items.Add(sFileName + ": Transfered.")));
//Close Connection
networkStream.Close();
handlerSocket = null; //Clear socket
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
現在我已經調試,並且至今我可以確定,第一次我可以看到一個問題是當w e試圖確定代碼讀取的文件名長度int iFileNameLength = BitConverter.ToInt32(rcvdData, 0);
- 當調試這個變量總是被確定爲'0',我認爲這是不正確的?我不確定。需要實現的所需結果是服務器應該接收文件,並且在成功傳輸後,文件名應顯示在列表框中。
這裏是在我遇到問題的屏幕截圖:
我的經驗和專長在別處,這是我第一次在這種模式下進行編碼(文件傳輸通過網絡)。然而,我的確有OSI模型和TCP/IP協議棧的理論知識,但從來沒有編碼過這樣的東西。給我的一個注意事項是,服務器的編碼假定它將在特定的PC上執行,並且如果絕對必要,我可以更改服務器應用程序的代碼。
'dataByte.CopyTo(rcvdData,I);'是錯誤的,'iRcvdBytes <= iBlockSize',你把它當作'iRcvdBytes == iBlockSize || iRcvdBytes == 0'。 'dataByte'在你拷貝到'rcvdData'的數組末尾有「垃圾數據」。 –