我必须开发一个简单的TCP文件传输客户端作为练习/演示的一部分,但我在数据传输方面遇到了麻烦。
我已经提供了TCP文件服务器,它将接收传入的文件,我必须编写一个客户端,它将连接到服务器并将文件发送到服务器。到目前为止,我已成功将所选文件的数据转换为准备传输并成功打开连接然后发送数据的格式,但是即使在接收的服务器上遇到问题 - 我也不被允许更改服务器的代码,因此应更改我的客户端代码,以便服务器可以解释发送的数据。这是我使用的代码(有些是遗漏的,这是一个简单的开销,比如输入框来获取IP地址等):
TCP服务器VS解决方案的链接(如果您愿意):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只是OpenFileDialog的完整文件路径+文件名。
以下是服务器的加载方法:
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);
}
}
现在我已经调试了,到目前为止我可以确定,第一次看到问题的时候我们正在尝试确定代码读取的文件名长度int iFileNameLength = BitConverter.ToInt32(rcvdData, 0);
- 调试此变量时始终确定为'0',我认为这是不正确的?我不确定。需要实现的结果是服务器应该接收文件,成功传输后,文件名应该显示在ListBox中。
以下是显示我遇到的问题的屏幕截图:
我的经验和专业知识在其他地方,这是我第一次在这个范例内编码(通过网络传输文件)。然而,我确实有关于/研究OSI模型和TCP / IP协议栈的理论知识,但从未编写任何类似的东西。给我的一个注意事项是服务器编码时假设它将在特定的PC上执行,如果绝对必要,我可以更改服务器应用程序的代码。
答案 0 :(得分:1)
您应该注意的服务器代码有两件事
/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 :(得分:1)
试试这个。你必须在客户端上反向思考并使用List使事情变得更容易。
Cache