C# 简单通信(实现文件传输)
https://blog.csdn.net/Sayesan/article/details/82185772
之前写过一个简单通信传输,不过只有聊天的功能,现在实现了文件传输的功能,借鉴于网上一篇博客,不过他写的仅仅是客户端对于服务器发送文件,我稍微优化了这个功能,实现了,端与端之间信息的互发和文件的互发,感觉学习这些新的东西,还刚开始,进度很慢,很多东西都需要从新去学习,不过慢慢来!Fighting!!!
服务器:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Net;using System.Net.Sockets;using System.Threading;using System.IO;namespace EasyChat{public partial class Server : Form{public Server(){InitializeComponent();//关闭对文本框的非法线程操作检查TextBox.CheckForIllegalCrossThreadCalls = false;}private void Server_Load(object sender, EventArgs e){textIP.AppendText("127.0.0.1");textPORT.AppendText("5555");}Thread threadWatch = null;Socket socketWatch = null;private void ServerBegin_Click(object sender, EventArgs e){//定义一个套接字,监听发来的信息,包含3个参数(IP4寻址协议,流式连接,TCP协议)socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);int port = Convert.ToInt32(textPORT.Text.Trim());IPAddress ip = IPAddress.Parse(textIP.Text.Trim());//绑定IP地址和端口号IPEndPoint ipe = new IPEndPoint(ip, port);socketWatch.Bind(ipe);socketWatch.Listen(20);//监听队列长度,20//负责监听的线程threadWatch = new Thread(WatchConnect);//。。。threadWatch.IsBackground = true;threadWatch.Start();Message.AppendText("服务器已经启动,开始监听..."+"\r\n");}Socket socketConnect = null;private void WatchConnect(){while (true){try{socketConnect = socketWatch.Accept();}catch (Exception ex){Message.AppendText(ex.Message);break;}Message.AppendText("客户端连接成功,可以开始通信..."+"\r\n");//创建通信线程,感觉这个和Thread的区别,就是这个有参,另一个无参ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRec);Thread thr = new Thread(pts);thr.Start(socketConnect);}}string recStr = null;private void ServerRec(object obj){Socket socketServer = obj as Socket;long fileLength = 0;while (true){int firstRcv = 0;byte[] buffer = new byte[8 * 1024];try{//获取接受数据的长度,存入内存缓冲区,返回一个字节数组的长度if (socketServer != null) firstRcv = socketServer.Receive(buffer);if (firstRcv > 0)//大于0,说明有东西传过来{if (buffer[0] == 0)//0对应文字信息{recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);Message.AppendText("ZXY: " + GetTime() + "\r\n" + recStr + "\r\n");}if (buffer[0] == 1)//1对应文件信息{string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));SaveFileDialog sfDialog = new SaveFileDialog(){Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",FileName = recStr};if (sfDialog.ShowDialog(this) == DialogResult.OK){string savePath = sfDialog.FileName;int rec = 0;long recFileLength = 0;bool firstWrite = true;using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write)){while (recFileLength < fileLength){if (firstWrite){fs.Write(buffer, 1, firstRcv - 1);fs.Flush();recFileLength += firstRcv - 1;firstWrite = false;}else{rec = socketServer.Receive(buffer);fs.Write(buffer, 0, rec);fs.Flush();recFileLength += rec;}}fs.Close();}string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));Message.AppendText("ZXY: " + GetTime() + "\r\n你成功接收了文件..." + fName + "\r\n保存路径为:" + fPath + "\r\n");}}if (buffer[0] == 2)//2对应文件名字和长度{string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);recStr = fileNameWithLength.Split('-').First();fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());}}}catch (Exception ex){Message.AppendText("系统异常..." + ex.Message);break;}}}private void ServerSend(string SendStr,byte symbol){//用UTF8能接受文字信息byte[] buffer = Encoding.UTF8.GetBytes(SendStr);//实际发送的字节数组比实际输入的长度多1,用于存取标识符byte[] newBuffer = new byte[buffer.Length+1];//标识符添加在位置为0的地方newBuffer[0] = symbol;Buffer.BlockCopy(buffer,0,newBuffer,1,buffer.Length);socketConnect.Send(newBuffer);Message.AppendText("PYT: "+ GetTime() + "\r\n" + SendStr+"\r\n");}string filePath = null;string fileName = null;private void Select_Click(object sender, EventArgs e){OpenFileDialog ofDialog = new OpenFileDialog();if(ofDialog.ShowDialog(this) == DialogResult.OK){fileName = ofDialog.SafeFileName;//获取选取文件的文件名File.Text = fileName;//将文件名显示在文本框上filePath = ofDialog.FileName;//获取包含文件名的全路径}}private void SendFile(string fileFullPath){if (string.IsNullOrEmpty(fileFullPath)){MessageBox.Show(@"请选择需要发送的文件!");return;}//发送文件前,将文件名和长度发过去long fileLength = new FileInfo(fileFullPath).Length;string totalMsg = string.Format("{0}-{1}", fileName, fileLength);ServerSend(totalMsg, 2);byte[] buffer = new byte[8*1024];using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read)){int readLength = 0;bool firstRead = true;long sentFileLength = 0;while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength){sentFileLength += readLength;//第一次发送的字节流上加个前缀1if (firstRead){byte[] firstBuffer = new byte[readLength + 1];//标记1,代表为文件firstBuffer[0] = 1;Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);socketConnect.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);firstRead = false;continue;}socketConnect.Send(buffer, 0, readLength, SocketFlags.None);}fs.Close();}Message.AppendText("SoFlash:" + GetTime() + "\r\n您发送了文件:" + fileName + "\r\n");}private void Send_Click(object sender, EventArgs e){ServerSend(SendMsg.Text,0);}private void SendMsg_keyDown(object sender, KeyEventArgs e)//Enter发送{if (e.KeyCode == Keys.Enter){ServerSend(SendMsg.Text,0);}}private void Sendfile_Click(object sender, EventArgs e){SendFile(filePath);}public DateTime GetTime()//获取系统时间{DateTime now = new DateTime();now = DateTime.Now;return now;}}}
客户端:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Net;using System.Net.Sockets;using System.Threading;using System.IO;namespace EasyChats{public partial class Client : Form{public Client(){InitializeComponent();TextBox.CheckForIllegalCrossThreadCalls = false;}private void Client_Load(object sender, EventArgs e){textIP.AppendText("127.0.0.1");textPort.AppendText("5555");}Socket socketClient = null;Thread threadClient = null;private void BeginClient_Click(object sender, EventArgs e){socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);int port = Convert.ToInt32(textPort.Text.Trim());IPAddress ip = IPAddress.Parse(textIP.Text.Trim());IPEndPoint ipe = new IPEndPoint(ip, port);socketClient.Connect(ipe);threadClient = new Thread(RecMsg);threadClient.IsBackground = true;threadClient.Start();Message.AppendText("已经与服务端建立连接,可以开始通信...\r\n");}private void RecMsg(){long fileLength = 0;string recStr = null;while (true){int firstRcv = 0;byte[] buffer = new byte[8 * 1024];try{if (socketClient != null) firstRcv = socketClient.Receive(buffer);if (firstRcv > 0){if (buffer[0] == 0){recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);Message.AppendText("PYT: " + GetTime() + "\r\n" + recStr + "\r\n");}if (buffer[0] == 1){string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));SaveFileDialog sfDialog = new SaveFileDialog(){Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",FileName = recStr};if (sfDialog.ShowDialog(this) == DialogResult.OK){string savePath = sfDialog.FileName;int rec = 0;long recFileLength = 0;bool firstWrite = true;using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write)){while (recFileLength < fileLength){if (firstWrite){fs.Write(buffer, 1, firstRcv - 1);fs.Flush();recFileLength += firstRcv - 1;firstWrite = false;}else{rec = socketClient.Receive(buffer);fs.Write(buffer, 0, rec);fs.Flush();recFileLength += rec;}}fs.Close();}string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));Message.AppendText("ZXY: " + GetTime() + "\r\n你成功接收了文件..." + fName + "\r\n保存路径为:" + fPath + "\r\n");}}if (buffer[0] == 2){string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);recStr = fileNameWithLength.Split('-').First();fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());}}}catch (Exception ex){Message.AppendText("系统异常..." + ex.Message);break;}}}private void ClientSend(string SendStr, byte symbol){byte[] buffer = Encoding.UTF8.GetBytes(SendStr);byte[] newBuffer = new byte[buffer.Length + 1];newBuffer[0] = symbol;Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);socketClient.Send(newBuffer);Message.AppendText("ZXY: " + GetTime() + "\r\n" + SendStr + "\r\n");}private void Send_Click_1(object sender, EventArgs e){ClientSend(SendMsg.Text, 0);}string filePath = null;string fileName = null;private void fileSelect_Click(object sender, EventArgs e){OpenFileDialog ofDialog = new OpenFileDialog();if (ofDialog.ShowDialog(this) == DialogResult.OK){fileName = ofDialog.SafeFileName;FileName.Text = fileName;filePath = ofDialog.FileName;}}private void fileSend_Click(object sender, EventArgs e){SendFile(filePath);}private void SendFile(string fileFullPath){if (string.IsNullOrEmpty(fileFullPath)){MessageBox.Show(@"请选择需要发送的文件...");return;}long fileLength = new FileInfo(fileFullPath).Length;string totalMsg = string.Format("{0}-{1}", fileName, fileLength);ClientSend(totalMsg, 2);byte[] buffer = new byte[2 * 1024];using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read)){int readLength = 0;bool firstRead = true;long sentFileLength = 0;while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength){sentFileLength += readLength;if (firstRead){byte[] firstBuffer = new byte[readLength + 1];firstBuffer[0] = 1;Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);firstRead = false;}else{socketClient.Send(buffer, 0, readLength, SocketFlags.None);}}fs.Close();}Message.AppendText("ZXY:" + GetTime() + "\r\n你发送了文件:" + fileName + "\r\n");}private void Send_Click(object sender, EventArgs e){ClientSend(SendMsg.Text, 0);}private void SendMsg_keyDown(object sender, KeyEventArgs e){if (e.KeyCode == Keys.Enter){ClientSend(SendMsg.Text, 0);}}private void Sendfile_Click(object sender, EventArgs e){SendFile(filePath);}public DateTime GetTime(){DateTime now = new DateTime();now = DateTime.Now;return now;}}}
对于线程的IsBackground的理解,摘自于网络:
1、当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的。
2、当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行结束。
3、只有IsBackground=TRUE的线程才会随着主线程的退出而退出。
4、当初始化一个线程,把Thread.IsBackground=true的时候,指示该线程为后台线程。后台线程将会随着主线程的退出而退出。
5、原理:只要所有前台线程都终止后,CLR就会对每一个活在的后台线程调用Abort()来彻底终止应用程序。
C# 简单通信(实现文件传输)的更多相关文章
- 基于UDT connect连接通信以及文件传输--服务端
网上与UDT相关的资料不多,与UDT相关的源码例子更少.最近在接触UDT,也是因为缺少相关的资料,导致学习起来甚感痛苦.下面将我自己这两天弄出来的代码贴出来,希望对在寻找相关资料的童鞋有一定的帮助.与 ...
- 基于UDT connect连接通信以及文件传输--客户端
上面一篇文章中提出了服务端的,其实这里没有严格意义的服务端和客户端之分,因为我在代码中是基于UDP的,不存在服务端与客户端,两个都是对等的,只是我这里进行一下简单的区分而已.在这里,客户端所进行的主要 ...
- NAT穿透进行P2P文件传输
实现一个简单的p2p文件传输,主要解决NAT穿透问题,使用tcp协议传输. NAT背景介绍 简介 NAT(Network Address Translation ,网络地址转换) 是一种广泛应用的解决 ...
- QT从入门到入土(九)——TCP/IP网络通信(以及文件传输)
引言 TCP/IP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISO/OSI模型的四层层级构架的基础上通过TCP/IP协议建立的通讯.控制器可以设置 ...
- 【RL-TCPnet网络教程】第38章 TFTP简单文件传输基础知识
第38章 TFTP简单文件传输基础知识 本章节为大家讲解TFTP(Trivial File Transfer Protocol,简单文件传输协议)的基础知识,方便后面章节的实战操作. (本章 ...
- Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输
一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...
- 网络编程 - socket通信/粘包/文件传输/udp - 总结
socket通信 1.简单的套接字通信 import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bin ...
- tftp简单文件传输协议搭建
TFTP 简单文件传输协议 安装 sudo apt-get install tftp tftpd openbsd-inetd 需要tftp tftpd openbsd-ine ...
- python 全栈开发,Day129(玩具开机提示语,为多个玩具发送点播,聊天界面,app录音,app与服务器端文件传输,简单的对话)
一.玩具开机提示语 先下载github代码,下面的操作,都是基于这个版本来的! https://github.com/987334176/Intelligent_toy/archive/v1.2.zi ...
随机推荐
- 2 Android程序的执行
Android系统采用的是分层架构,分四层: 1. Applicitations:应用层 2. Applicitation Framework:架构层 3. Libraries:类库层 4. ...
- Hibernate 5.x 生成 SessionFactory 源码跟踪分析
我们要使用 Hibernate 的功能,首先需要读取 Hibernate 的配置文件,根据配置启动 Hibernate ,然后创建 SessionFactory. 创建 SessionFactory ...
- java虚拟机类加载机制和双亲委派模型
java虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型. 类的生命周期是从类被加载到虚拟机内存中,到卸 ...
- 微博api接口登陆,获取信息,分享微博
import json from datetime import datetime import MySQLdb import requests from flask import Flask, re ...
- php备忘录模式(memento pattern)
晚上刷起来. <?php /* The memento pattern provides the object restore functionality. Implementation is ...
- 1062 Error 'Duplicate entry '1438019' for key 'PRIMARY'' on query
mysql主从库同步错误:1062 Error 'Duplicate entry '1438019' for key 'PRIMARY'' on querymysql主从库在同步时会发生1062 La ...
- qt 静态库中貌似不能使用静态属性
今天一个问题搞的很郁闷,原本好好的工程,这两天加了几个类之后链接不通过了. 发现过程略去不说,最后去掉了类中的static属性,编译通过了.具体原因没时间仔细查了,反正尽量避免在静态链接库里使用sta ...
- KVM-安装windows
硬盘.网卡选择vitio 虚拟机配置2个cd-rom,分别挂载系统iso与virtio-win 开始安装无法识别硬盘,加载光驱驱动 安装完成进入系统之后,设备管理器添加驱动,识别设备
- 输入一个表示整数的字符串,把该字符串转换成整数并输出(实现atoi函数功能)
例如输入字符串"345",则输出整数345.-----------------------------此题一点也不简单.不信,你就先不看一下的代码,你自己先写一份,然后再对比一下, ...
- c语言位域的使用注意事项——数据溢出
c语言可以使用位域来节省变量的空间,例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位.位域的取值范围非常有限,数据稍微大些就会发生溢出,这个字使用keil的使用,keil提 ...