使用TCP文件传输客户端发送时遇到问题
我必须开发一个简单的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上执行,并且如果绝对必要,我可以更改服务器应用程序的代码。
试试这个。您必须在客户端反过来思考,并使用列表使事情变得更容易。
private void TransferFile(string _sFileName, string _sIPAdress)
{
List<Byte> bFileBuffer = File.ReadAllBytes(_sFileName).ToList();
byte[] bFileName = Encoding.ASCII.GetBytes(_sFileName);
bFileBuffer.InsertRange(0, bFileName);
//Get the File name length, BitConvertor occupies the first 4 bytes
byte[] brcvdDataCount = BitConverter.GetBytes((UInt32)_sFileName.Count());
bFileBuffer.InsertRange(0, brcvdDataCount);
//Open TCP/IP Connection
TcpClient tcpClientSocket = new TcpClient(_sIPAdress, 8080);
NetworkStream nsNetworkStream = tcpClientSocket.GetStream();
nsNetworkStream.Write(bFileBuffer.ToArray(), 0, bFileBuffer.Count);
nsNetworkStream.Close();
}
我明白了,但有没有办法做到这一点,而无需更改服务器代码?就像我在通过客户端发送数据时如何使用ASCII编码而不是使用字节? –
我没有更改服务器代码。服务器正在接收字节,我正在发送字节。服务器期望文件名长度是前四个字节,然后是文件名,然后是数据。 – jdweng
理解,但我该如何解决这个问题,我如何在客户端做相反的事情?我更新了我的帖子,以包括我的问题的屏幕截图。对不起,我对这个问题深感不满。 –
有两件事与服务器代码,你应该知道的
/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);
1)你需要一个字节计数添加到上传的开始。 2)代码使用Ascii编码,这意味着你不能上传二进制数据。
我明白了。我将如何(1)在发送时添加字节计数和(2)使用ASCII编码对数据进行编码?谢谢。 –
'dataByte.CopyTo(rcvdData,I);'是错误的,'iRcvdBytes