C#网络编程接收文件Part5.docx
- 文档编号:9138577
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:8
- 大小:18.31KB
C#网络编程接收文件Part5.docx
《C#网络编程接收文件Part5.docx》由会员分享,可在线阅读,更多相关《C#网络编程接收文件Part5.docx(8页珍藏版)》请在冰豆网上搜索。
C#网络编程接收文件Part5
C#网络编程(接收文件)-Part.5
这篇文章将完成Part.4中剩余的部分,它们本来是一篇完整的文章,但是因为上一篇比较长,合并起来页数太多,浏览起来可能会比较不方便,我就将它拆为两篇了,本文便是它的后半部分。
我们继续进行上一篇没有完成的步骤:
客户端接收来自服务端的文件。
4.客户端接收文件
4.1服务端的实现
对于服务端,我们只需要实现上一章遗留的sendFile()方法就可以了,它起初在handleProtocol中是注释掉的。
另外,由于创建连接、获取流等操作与receiveFile()是没有区别的,所以我们将它提出来作为一个公共方法getStreamToClient()。
下面是服务端的代码,只包含新增改过的代码,对于原有方法我只给出了签名:
classServer{
staticvoidMain(string[]args){
Console.WriteLine("Serverisrunning...");
IPAddressip=IPAddress.Parse("127.0.0.1");
TcpListenerlistener=newTcpListener(ip,8500);
listener.Start(); //开启对控制端口8500的侦听
Console.WriteLine("StartListening...");
while(true){
//获取一个连接,同步方法,在此处中断
TcpClientclient=listener.AcceptTcpClient();
RemoteClientwapper=newRemoteClient(client);
wapper.BeginRead();
}
}
}
publicclassRemoteClient{
//字段略
publicRemoteClient(TcpClientclient){}
//开始进行读取
publicvoidBeginRead(){}
//再读取完成时进行回调
privatevoidOnReadComplete(IAsyncResultar){}
//处理protocol
privatevoidhandleProtocol(objectobj){
stringpro=objasstring;
ProtocolHelperhelper=newProtocolHelper(pro);
FileProtocolprotocol=helper.GetProtocol();
if(protocol.Mode==FileRequestMode.Send){
//客户端发送文件,对服务端来说则是接收文件
receiveFile(protocol);
}elseif(protocol.Mode==FileRequestMode.Receive){
//客户端接收文件,对服务端来说则是发送文件
sendFile(protocol);
}
}
//发送文件
privatevoidsendFile(FileProtocolprotocol){
TcpClientlocalClient;
NetworkStreamstreamToClient=getStreamToClient(protocol,outlocalClient);
//获得文件的路径
stringfilePath=Environment.CurrentDirectory+"/"+protocol.FileName;
//创建文件流
FileStreamfs=newFileStream(filePath,FileMode.Open,FileAccess.Read);
byte[]fileBuffer=newbyte[1024]; //每次传1KB
intbytesRead;
inttotalBytes=0;
//创建获取文件发送状态的类
SendStatusstatus=newSendStatus(filePath);
//将文件流转写入网络流
try{
do{
Thread.Sleep(10); //为了更好的视觉效果,暂停10毫秒:
-)
bytesRead=fs.Read(fileBuffer,0,fileBuffer.Length);
streamToClient.Write(fileBuffer,0,bytesRead);
totalBytes+=bytesRead; //发送了的字节数
status.PrintStatus(totalBytes);//打印发送状态
}while(bytesRead>0);
Console.WriteLine("Total{0}bytessent,Done!
",totalBytes);
}catch{
Console.WriteLine("Serverhaslost...");
}
streamToClient.Dispose();
fs.Dispose();
localClient.Close();
}
//接收文件
privatevoidreceiveFile(FileProtocolprotocol){}
//获取连接到远程的流--公共方法
privateNetworkStreamgetStreamToClient(FileProtocolprotocol,outTcpClientlocalClient){
//获取远程客户端的位置
IPEndPointendpoint=client.Client.RemoteEndPointasIPEndPoint;
IPAddressip=endpoint.Address;
//使用新端口号,获得远程用于接收文件的端口
endpoint=newIPEndPoint(ip,protocol.Port);
//连接到远程客户端
try{
localClient=newTcpClient();
localClient.Connect(endpoint);
}catch{
Console.WriteLine("无法连接到客户端-->{0}",endpoint);
localClient=null;
returnnull;
}
//获取发送文件的流
NetworkStreamstreamToClient=localClient.GetStream();
returnstreamToClient;
}
//随机获取一个图片名称
privatestringgenerateFileName(stringfileName){}
}
服务端的sendFile方法和客户端的SendFile()方法完全类似,上面的代码几乎是一次编写成功的。
另外注意我将客户端使用的SendStatus类也拷贝到了服务端。
接下来我们看下客户端。
4.2客户端的实现
首先要注意的是客户端的SendFile()接收的参数是文件全路径,但是在写入到协议时只获取了路径中的文件名称。
这是因为服务端不需要知道文件在客户端的路径,所以协议中只写文件名;而为了使客户端的SendFile()方法更通用,所以它接收本地文件的全路径。
客户端的ReceiveFile()的实现也和服务端的receiveFile()方法类似,同样,由于要保存到本地,为了避免文件名重复,我将服务端的generateFileName()方法复制了过来。
publicclassServerClient:
IDisposable{
//字段略
publicServerClient(){}
//发送消息到服务端
publicvoidSendMessage(stringmsg){}
//发送文件-异步方法
publicvoidBeginSendFile(stringfilePath){ }
privatevoidSendFile(objectobj){}
//发送文件--同步方法
publicvoidSendFile(stringfilePath){}
//接收文件--异步方法
publicvoidBeginReceiveFile(stringfileName){
ParameterizedThreadStartstart=
newParameterizedThreadStart(ReceiveFile);
start.BeginInvoke(fileName,null,null);
}
publicvoidReceiveFile(objectobj){
stringfileName=objasstring;
ReceiveFile(fileName);
}
//接收文件--同步方法
publicvoidReceiveFile(stringfileName){
IPAddressip=IPAddress.Parse("127.0.0.1");
TcpListenerlistener=newTcpListener(ip,0);
listener.Start();
//获取本地侦听的端口号
IPEndPointendPoint=listener.LocalEndpointasIPEndPoint;
intlisteningPort=endPoint.Port;
//获取发送的协议字符串
FileProtocolprotocol=
newFileProtocol(FileRequestMode.Receive,listeningPort,fileName);
stringpro=protocol.ToString();
SendMessage(pro); //发送协议到服务端
//中断,等待远程连接
TcpClientlocalClient=listener.AcceptTcpClient();
Console.WriteLine("Startsendingfile...");
NetworkStreamstream=localClient.GetStream();
//获取文件保存的路劲
stringfilePath=
Environment.CurrentDirectory+"/"+generateFileName(fileName);
//创建文件流
FileStreamfs=newFileStream(filePath,FileMode.CreateNew,FileAccess.Write);
byte[]fileBuffer=newbyte[1024]; //每次传1KB
intbytesRead;
inttotalBytes=0;
//从缓存buffer中读入到文件流中
do{
bytesRead=stream.Read(buffer,0,BufferSize);
fs.Write(buffer,0,bytesRead);
totalBytes+=bytesRead;
Console.WriteLine("Receiving{0}bytes...",totalBytes);
}while(bytesRead>0);
Console.WriteLine("Total{0}bytesreceived,Done!
",totalBytes);
fs.Dispose();
stream.Dispose();
localClient.Close();
listener.Stop();
}
//随机获取一个图片名称
privatestringgenerateFileName(stringfileName){}
publicvoidDispose(){
if(streamToServer!
=null)
streamToServer.Dispose();
if(client!
=null)
client.Close();
}
}
上面关键的一句就是创建协议那句,注意到将mode由Send改为了Receive,同时传去了想要接收的服务端的文件名称。
4.3程序测试
现在我们已经完成了所有收发文件的步骤,可以看到服务端的所有操作都是被动的,接下来我们修改客户端的Main()程序,创建一个菜单,然后根据用户输入发送或者接收文件。
classProgram{
staticvoidMain(string[]args){
ServerClientclient=newServerClient();
stringinput;
stringpath=Environment.CurrentDirectory+"/";
do{
Console.WriteLine("SendFile:
S1-Client01.jpg,S2-Client02.jpg,S3-Client03.jpg");
Console.WriteLine("ReceiveFile:
R1-Server01.jpg,R1-Server02.jpg,R3-Server03.jpg");
Console.WriteLine("Press'Q'toexit.\n");
Console.Write("Enteryourchoice:
");
input=Console.ReadLine();
switch(input.ToUpper()){
case"S1":
client.BeginSendFile(path+"Client01.jpg");
break;
case"S2":
client.BeginSendFile(path+"Client02.jpg");
break;
case"S3":
client.BeginSendFile(path+"Client02.jpg");
break;
case"R1":
client.BeginReceiveFile("Server01.jpg");
break;
case"R2":
client.BeginReceiveFile("Server01.jpg");
break;
case"R3":
client.BeginReceiveFile("Server01.jpg");
break;
}
}while(input.ToUpper()!
="Q");
client.Dispose();
}
}
由于这是一个控制台应用程序,并且采用了异步操作,所以这个菜单的出现顺序有点混乱。
我这里描述起来比较困难,你将代码下载下来后运行一下就知道了:
-)
程序的运行结果和上一节类似,这里我就不再贴图了。
接下来是本系列的最后一篇,将发送字符串与传输文件的功能结合起来,创建一个可以发送消息并能收发文件的聊天程序,至于语音聊天嘛...等我学习了再告诉你>_<、
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C#网络编程接收文件 Part5 C# 网络 编程 接收 文件