Socket 中级篇(三)C# Socket的同步连接和异步连接区别:大规模客服端连接、少开线程、高性能

您所在的位置:网站首页 异步与同步通信的区别 Socket 中级篇(三)C# Socket的同步连接和异步连接区别:大规模客服端连接、少开线程、高性能

Socket 中级篇(三)C# Socket的同步连接和异步连接区别:大规模客服端连接、少开线程、高性能

2024-07-12 08:51| 来源: 网络整理| 查看: 265

目录

参考:

一、简介

1.1、提出问题

1.2、问题分析 

1.3、拓展Socket的同步连接与异步连接

1.3.1、什么是同步连接、异步连接

二、Socket同步通信实现

2.1、Server

2.2、Client

三、Socket异步通信实现

参考:

https://www.debugease.com/csharp/1114414.html

一、简介 1.1、提出问题

      服务端明明监听到一个服务端,但是却没有连接成功,如下所示:

服务端的监听源码:

using KeenRay.Common; using KeenRay.Common.SocketCommu; using Prism.Commands; using Prism.Events; using Prism.Mvvm; using Prism.Regions; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; using System.Windows.Threading; using System.Xml.Linq; namespace KeenRay.SocketCommu { public class SocketCommuInit : BindableBase { #region 属性集 //服务端 public Socket Client { get; set; } public int _receiveFlagValue = 0; /// /// 接收标志值 /// public int ReceiveFlagValue { get { return _receiveFlagValue; } set { SetProperty(ref _receiveFlagValue, value); } } #endregion #region 字段集 SocketCommuReceive socketCommuReceive = new SocketCommuReceive(); //服务器 Socket Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //监听多个Client Dictionary clientList = new Dictionary(); //IP string strSocketIP = null; //端口号 int point = 40000; #endregion #region 方法集 #region 单例 private volatile static SocketCommuInit _instance = null; private static readonly object lockobj = new object(); /// /// 创建实例 /// /// public static SocketCommuInit CreateInstance() { if (_instance == null) { lock (lockobj) { if (_instance == null) { _instance = new SocketCommuInit(); } } } return _instance; } #endregion #region IP配置 /// /// IP、端口配置 /// public void IPandPortConfig() { try { string strSocketConfigFilePath; strSocketConfigFilePath = Environment.CurrentDirectory + "\\Config" + "\\SocketAndBullHeadConfig.xml"; XDocument SocketDocument = XDocument.Load(strSocketConfigFilePath); XElement SocketRoot = SocketDocument.Root; //Socket节点 XElement SocketPoint = SocketRoot.Element("Socket"); //IP XElement SocketIP = SocketPoint.Element("SocketIP"); strSocketIP = SocketIP.Value; //端口 XElement SocketPort = SocketPoint.Element("SocketPort"); point = Convert.ToInt32(SocketPort.Value); } catch(Exception ex) { LogHelper.Error("SocketClass.cs::IPandPortConfig() IP/端口配置发生错误:--------------" + ex.ToString()); } } #endregion #region 启动Socket /// /// 启动 /// public void StartFlag() { //启动Socket string strSocketStartFlag = null; string strSocketConfigFilePath; strSocketConfigFilePath = Environment.CurrentDirectory + "\\Config" + "\\SocketAndBullHeadConfig.xml"; XDocument SocketDocument = XDocument.Load(strSocketConfigFilePath); XElement SocketRoot = SocketDocument.Root; //Socket节点 XElement SocketPoint = SocketRoot.Element("Socket"); //启动Socket XElement SocketStart = SocketPoint.Element("SocketStart"); strSocketStartFlag = SocketStart.Value; if (strSocketStartFlag == "1") { IPAddress IP = IPAddress.Parse(strSocketIP); IPEndPoint iPEndPoint = new IPEndPoint(IP, point); Server.Bind(iPEndPoint); Server.Listen(10); //开启线程监听 Thread th = new Thread(ListenFunc); th.IsBackground = true; th.Start(Server); } } #endregion #region 监听 /// /// 监听 /// /// public void ListenFunc(object Server) { while (true) { try { //客户端 Client = ((Socket)Server).Accept(); //clientList.Add(Client.RemoteEndPoint.ToString(), Client); //可以监听多个Client Thread threadServer = new Thread(new ParameterizedThreadStart(socketCommuReceive.Receive)); threadServer.IsBackground = true; threadServer.Start(Client); } catch (Exception ex) { LogHelper.Error("SocketClass.cs::Listen()监听发错了错误:--------------" + ex.ToString()); } } } #endregion #endregion } }

客户端的连接源码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Win32; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; using System.Windows.Threading; using KeenRayLargePC.Views; using System.Windows.Interop; using System.Xml.Linq; using System.Drawing.Imaging; using System.Drawing; using KeenRayLargePC.Common; using KeenRayLargePC.Config; using System.ComponentModel; using System.Windows.Forms.Integration; using AxKrayImgViewLib; using KeenRayLargePC.DicomOperate; using Prism.Commands; using KeenRayLargePC.PadDataAcessLayer; using KeenRayLargePC.PadDbContent; using System.Linq.Expressions; using KeenRayLargePC.Server; namespace KeenRayLargePC { public partial class MainWindow : Window,INotifyPropertyChanged { #region 命令集 /// /// 窗宽改变命令 /// public DelegateCommand SliderWWValueChangedCommand { get; private set; } /// /// 窗位改变命令 /// public DelegateCommand SliderWLValueChangedCommand { get; private set; } #endregion #region 属性集 BitmapImage bmpImage = null; public BitmapImage BmpImage { get { return bmpImage; } set { bmpImage = value; RaiseChanged("VideoImage"); } } public event PropertyChangedEventHandler PropertyChanged; public void RaiseChanged(string property) { if (PropertyChanged != null) { PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property)); } } private int _winWidth = 1; /// /// 窗宽 /// public int WinWidth { get { return _winWidth; } set { _winWidth = value; if (PropertyChanged != null) { //RaisePropertyChanged("PopupEraserMoreIsOpen"); PropertyChanged(this, new PropertyChangedEventArgs("WinWidth")); } } } private int _winLevel = 1; /// /// 窗位 /// public int WinLevel { get { return _winLevel; } set { _winLevel = value; if (PropertyChanged != null) { //RaisePropertyChanged("PopupEraserMoreIsOpen"); PropertyChanged(this, new PropertyChangedEventArgs("WinLevel")); } } } private bool _popupEraserMoreIsOpen; /// /// 清除菜单是否打开 /// public bool PopupEraserMoreIsOpen { get { return _popupEraserMoreIsOpen; } set { _popupEraserMoreIsOpen = value; if (PropertyChanged != null) { //RaisePropertyChanged("PopupEraserMoreIsOpen"); PropertyChanged(this, new PropertyChangedEventArgs("PopupEraserMoreIsOpen")); } } } #endregion #region 标志集 /*页面标志*/ const int HOMEPAGE_FLAG = 1; const int STUDYPAGE_FLAG = 2; const int REVIEWPAGE_FLAG = 3; /*曝光参数标志*/ const int KV_PLUS_FLAG = 11; const int KV_REDUCE_FLAG = 12; const int MA_PLUS_FLAG = 13; const int MA_REDUCE_FLAG = 14; const int MS_PLUS_FLAG = 15; const int MS_REDUCE_FLAG = 16; const int MAS_PLUS_FLAG = 17; const int MAS_REDUCE_FLAG = 18; const int MAS_MODE_FLAG = 19; const int MAMS_MODE_FLAG = 20; const int FOCUS_FLAG = 21; const int START_EXPOSE_FLAG = 22;//启动曝光按钮 const int SAVE_EXPOSE_VALUE = 23;//保存曝光参数 /*导航状态标志*/ const int OPEN_VIDEO_FLAG = 31;//打开视频监控 const int CLOSE_VIDEO_FLAG = 32;//关闭视屏监控 const int PANEL_TEMP_FLAG = 33; //平板温度 const int HEAT_CAPACITY_FLAG = 34;//热容量 const int BATTERY_CAPACITY_FLAG = 35;//电池容量 const int EXPOSE_STATUS_FLAG = 36;//曝光状态。接收到的内容(int),0:就绪。1:预备。2:曝光。3:禁止。 /*其他信息标志*/ const int DICOM_FLAG = 41; //Dicom const int USER_INFO_FLAG = 42; //用户信息 /*状态标志*/ bool blStartFlag = false; //Socket启动标志 bool imageEditFlag = false; //图像编辑标识 bool blCameraRecStatue = false; //视频监控开关状态。false:关闭。true:打开。 bool blImageRecStatue = false; bool blCommonRecStatue = false; //其他状态开关标志 const string strCameraRecStatue = "CameraRecStatue"; const string strImageRecStatue = "ImageRecStatue"; const string strCommonRecStatue = "CommonRecStatue"; bool blUpdateTimeFlag = true; //是否运行实时更新时间 bool blCanAnalysisPackageHead = true; //是否允许解析包头 bool blCanAnalysisPackageContent = true; //是否允许解析包内容 #endregion #region 属性集 #region 图像显示控件属性 public bool m_bEditFlag = false; //编辑标志 public int m_nGrabAcqStatus; //0-DR 1-RF 2-SPOT public int nWindowLevel; //窗位 public int nWindowWidth; //窗宽 public KrayDicomLib.DicomFile m_cDicomFile; ImgViewHandle handle = new ImgViewHandle(); #endregion #region 包属性:用来解析包,实现被动接收,如接收Dicom,用户信息 byte[] bytPageType = new byte[4]; //页面类型 byte[] bytRecFlag = new byte[4]; //标志位字节 byte[] bytContentLong = new byte[4]; //长度字节 byte[] bytContent = new byte[0]; //内容 int iPageFlag = -1; //页面类型 int iRecFlag = -1; //接收标志 int iContentLong = -1; //包内容长度 int iPathLong = -1; //Dicom图路径长度 const int FLAG_LENGTH = 12; //包头长度 #endregion #region Dicom图操作 PatientInfoDal patientInfoDal = new PatientInfoDal(); SeriesInfoDal seriesInfoDal = new SeriesInfoDal(); ImagesInfoDal imagesInfoDal = new ImagesInfoDal(); List patientInfoList = new List(); List seriesInfoList = new List(); List imagesInfoList = new List(); #endregion #region 视频监控属性 List VideoList = new List(); //存放视频帧 const int BITMAP_IMAGE_LENGTH = 921654; //帧字节长度 byte[] btCurrentBitmapImage = new byte[BITMAP_IMAGE_LENGTH];//当前帧 byte[] btLastBitmapImage = new byte[BITMAP_IMAGE_LENGTH]; //上一帧 #endregion #region Socket通用属性 List bufferList = new List(); //缓存队列 byte[] btRecBuffer = new byte[16* 1000 * 1000];//socket接收缓存区 int Port = 50000;//端口号 IPAddress IP = IPAddress.Parse("127.0.0.1"); IpConfig ipConfig = new IpConfig(); IPEndPoint serverIPEndPoint = null; public Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Log log = Log.CreateInstance();//日志类 iPadReceive ipadReceive = iPadReceive.CreateInstance(); iPadSend ipadSend = iPadSend.CreateInstance(); InitPacs initPacs = InitPacs.CreateInstance();//启动Pacs初始配置。 SendModality sendModality = SendModality.CreateInstance(); #endregion #endregion #region 方法集 #region 单例 //public volatile static MainWindow _instance = null; //public static readonly object lockobj = new object(); / / 创建实例 / / //public static MainWindow CreateInstance() //{ // if (_instance == null) // { // lock (lockobj) // { // if (_instance == null) // { // _instance = this; // } // } // } // return _instance; //} #endregion /// /// 默认构造函数 /// public MainWindow() { //InitializeComponent(); log.ClearLogFunc();//清除日志 ipadReceive.setMainWindowDeleaget(this); ipadSend.setMainWindowDeleaget(this); //更新UI: 可以用 App.Current.Dispatcher.Invoke((Action)delegate () { this.DataContext = this; }); //窗宽改变命令初始化 SliderWWValueChangedCommand = new DelegateCommand(SliderWWValueChangedFun); //窗位改变命令初始化 SliderWLValueChangedCommand = new DelegateCommand(SliderWLValueChangedFun); m_nGrabAcqStatus = 0; nWindowWidth = 65535; nWindowLevel = 32768; //获取配置文件默认的IP、Port ipConfig.IpConfigFunc(ref blStartFlag, ref IP, ref Port); StartFunc();//默认就启动Socket连接PC /* 线程更新时间 */ Thread UpdateTimeThread = new Thread(UpdateTime); UpdateTimeThread.IsBackground = true; UpdateTimeThread.Start(); } /// /// 启动 /// private void StartFunc() { try { if (blStartFlag == true) { serverIPEndPoint = new IPEndPoint(IP, Port); //获得要连接的远程服务器应用程序的IP地址和端口号 Client.Connect(serverIPEndPoint); if (Client.Connected == true) { log.WriteDebugLogFunc("MainWindow.xaml.cs::StartFunc()——" + "已连接服务器" + "\n\n"); MessageBox.Show("连接服务器状态:成功"); /*开线程接收*/ Thread threadReceive = new Thread(ipadReceive.Receive); threadReceive.IsBackground = true; threadReceive.Start(Client); /*开线程发送归档状态信息*/ Thread thSendModality = new Thread(sendModality.SendImageArchiveFunc2); thSendModality.IsBackground = true; thSendModality.Start(); } else { log.WriteDebugLogFunc("MainWindow.xaml.cs::StartFunc()——" + "服务器已经开启,但无法连接服务器" + "\n\n"); } } } catch (Exception ex) { //MessageBox.Show("服务器未开启或客户端输入的IP不正确"); log.WriteErrorLogFunc("MainWindow.xaml.cs::StartFunc()——" + "服务器未开启或客户端输入的IP不正确:" + ex.ToString() + "\n\n"); } } /// /// 导图:iPads导图到Pacs /// /// /// private void btn_SendPacs_Click(object sender, RoutedEventArgs e) { try { Pacs pacsDialog = new Pacs(); pacsDialog.SetValidServerList(); pacsDialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; pacsDialog.ShowDialog(); } catch (Exception ex) { log.WriteErrorLogFunc("MainWindow.xaml.cs::btn_Image_Click()——" + "视频监控开关状态发送错误:" + ex.ToString() + "\n\n"); } } /// /// 关闭系统 /// /// /// private void BtnSysShutDown_Click(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } /// /// 系统配置,弹窗window窗口 /// /// /// private void btnSystemConfig_Click(object sender, RoutedEventArgs e) { try { if (Client != null && Client.Connected == true) { MessageBox.Show("Pad已经连上PC,无需配置IP/Port了"); return; } SystemConfigWindow systemConfigWindow = new SystemConfigWindow(); systemConfigWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen; if (systemConfigWindow.ShowDialog() == true) { IP = IPAddress.Parse(systemConfigWindow.IP); Port = systemConfigWindow.Port; blStartFlag = true;//若是IP配置正确,则启动Socket连接 } StartFunc();//启动Socket连接 } catch(Exception ex) { log.WriteErrorLogFunc("MainWindow.xaml.cs::btnSystemConfig_Click()——" + "IP格式或端口不正确:" + ex.ToString() + "\n\n"); } } #region 更新时间 /// /// 更新时间 /// private void UpdateTime() { while (blUpdateTimeFlag == true) { Thread.Sleep(1000); //更新UI: 可以用 App.Current.Dispatcher.Invoke((Action)delegate () { this.lblDateTime_Second.Content = DateTime.Now.ToLongTimeString().ToString(); this.lblDateTime_day.Content = DateTime.Now.ToString("yyyy-MM-dd"); }); } } #endregion #region 发送视频监控 /// /// 视频监控开关状态 /// /// /// private void Camera_Click(object sender, RoutedEventArgs e) { try { if (blCameraRecStatue == false)//如果在关闭状态下,那就打开它。 { //视频打开,其他功能必须关闭 ModuleRunFlagFunc(strCameraRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, OPEN_VIDEO_FLAG, null); } else if (blCameraRecStatue == true)// 如果在打开状态下,那就关闭它。 { blCameraRecStatue = false; ipadSend.SendPackageFunc(STUDYPAGE_FLAG, CLOSE_VIDEO_FLAG, null); //关闭视频监控下,必须清空Image的画面 App.Current.Dispatcher.Invoke((Action)delegate () { imgDisPlay.Source = null; }); } } catch (Exception ex) { log.WriteErrorLogFunc("MainWindow.xaml.cs::Camera_Click()——" + "视频监控开关状态发送错误:" + ex.ToString() + "\n\n"); } } #endregion #region 发送曝光标志 /// /// 启动曝光 /// /// /// private void btnExpose_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, START_EXPOSE_FLAG, null); } private void btn_KvPlus_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, KV_PLUS_FLAG, null); } private void btn_KvReduce_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, KV_REDUCE_FLAG, null); } private void btn_mAPlus_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MA_PLUS_FLAG, null); } private void btn_mAReduce_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MA_REDUCE_FLAG, null); } private void btn_msPlus_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MS_PLUS_FLAG, null); } private void btn_msReduce_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MS_REDUCE_FLAG, null); } private void btn_mAsPlus_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MAS_PLUS_FLAG, null); } private void btn_mAsReduce_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MAS_REDUCE_FLAG, null); } private void btn_mAsMode_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MAS_MODE_FLAG, null); } private void btn_mAmsMode_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, MAMS_MODE_FLAG, null); } /// /// 焦点 /// /// /// private void btn_Focus_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, FOCUS_FLAG, null); } private void btn_SaveExposeValues_Click(object sender, RoutedEventArgs e) { //其他功能必须关闭 ModuleRunFlagFunc(strCommonRecStatue); ipadSend.SendPackageFunc(STUDYPAGE_FLAG, SAVE_EXPOSE_VALUE, null); } #endregion /// /// 模块运行标志 /// /// public void ModuleRunFlagFunc(string str) { switch (str) { case strCameraRecStatue: blCameraRecStatue = true; blImageRecStatue = false; blCommonRecStatue = false; break; case strImageRecStatue: blCameraRecStatue = false; blImageRecStatue = true; blCommonRecStatue = false; //同时需要发一个信息给主程序,关闭视频监控,不让它发信息过来了。 ipadSend.SendPackageFunc(STUDYPAGE_FLAG, CLOSE_VIDEO_FLAG, null); //并且让当前的image清零 App.Current.Dispatcher.Invoke((Action)delegate () { this.imgDisPlay.Source = null; }); break; case strCommonRecStatue: //同时需要发一个信息给主程序,关闭视频监控,不让它发信息过来了。 ipadSend.SendPackageFunc(STUDYPAGE_FLAG, CLOSE_VIDEO_FLAG, null); //并且让当前的image清零 App.Current.Dispatcher.Invoke((Action)delegate () { this.imgDisPlay.Source = null; }); blCameraRecStatue = false; blImageRecStatue = false; blCommonRecStatue = true; break; default: break; } } #region Dicom图 /// /// 点击加载一张Dicom图:主要用来测试 /// /// /// private void OpenDicom_Click(object sender, RoutedEventArgs e) { try { /*直接打开*/ //System.Windows.Forms.OpenFileDialog open = new System.Windows.Forms.OpenFileDialog(); //open.Filter = "DCM图像文件|*.dcm"; //open.RestoreDirectory = false; //if (open.ShowDialog() == System.Windows.Forms.DialogResult.OK) //{ // handle.PutImage(this.imageview, open.FileName, ref m_cDicomFile); //} 适应窗口 //imageview.FtsImage(); //this.imageview.Invalidate(); 隐藏视频监控窗口 //this.imgDisPlay.Visibility = Visibility.Hidden; //this.host.Visibility = Visibility.Visible; /*调用ShowDicom打开*/ System.Windows.Forms.OpenFileDialog open = new System.Windows.Forms.OpenFileDialog(); open.Filter = "DCM图像文件|*.dcm"; open.RestoreDirectory = false; if (open.ShowDialog() == System.Windows.Forms.DialogResult.OK) { ipadReceive.ShowDicom(open.FileName); } } catch (Exception ex) { log.WriteErrorLogFunc("MainWindow.xaml.cs::OpenDicom_Click()——" + "打开dicom图发生错误:" + ex.ToString() + "\n\n"); } } /// /// 左旋转 /// /// /// private void btn_LeftRotate_Click(object sender, RoutedEventArgs e) { this.imageview.LeftRotate(); this.imageview.Invalidate(); } /// /// 右旋转 /// /// /// private void btn_RightRotate_Click(object sender, RoutedEventArgs e) { this.imageview.RightRotate(); this.imageview.Invalidate(); } /// /// 下侧翻 /// /// /// private void btn_DownFlip_Click(object sender, RoutedEventArgs e) { this.imageview.FlipVertical(); this.imageview.Invalidate(); } /// /// 右侧翻 /// /// /// private void btn_RightFlip_Click(object sender, RoutedEventArgs e) { this.imageview.FlipHorizon(); this.imageview.Invalidate(); } /// /// 等比显示:显示一张图 /// /// /// private void btn_ShowOneImage_Click(object sender, RoutedEventArgs e) { if (this.imageview.HasImage) { this.imageview.RealSizeImage(); this.imageview.Invalidate(); } } /// /// 全屏显示 /// /// /// private void btn_FullScreen_Click(object sender, RoutedEventArgs e) { //适应窗口 imageview.FtsImage(); imageview.Invalidate(); } /// /// 手抓移动 /// /// /// private void btn_AllowMove_Click(object sender, RoutedEventArgs e) { if (this.imageview.HasImage) { this.imageview.ProcType = KrayImgViewLib.tagPROC_TYPE.PT_MOVE; } } /// /// 禁止移动 /// /// /// private void btn_ForbiddenMove_Click(object sender, RoutedEventArgs e) { if (this.imageview.HasImage) { this.imageview.ProcType = KrayImgViewLib.tagPROC_TYPE.PT_NONE; this.imageview.Invalidate(); } } /// /// 右标记 /// /// /// private void btnR_Click(object sender, RoutedEventArgs e) { //string sFontName = configInfoModel.RLMarkFontName; //int nFontSize = configInfoModel.RLMarkFontSize; string sFontName = "微软雅黑"; int nFontSize = 200; if (this.imageview.HasImage) { this.imageview.DrawFlag = "R"; this.imageview.AddText(200, 30, "R", nFontSize, sFontName); this.imageview.ProcType = KrayImgViewLib.tagPROC_TYPE.PT_NONE; this.imageview.Invalidate(); SetEditFlag(true); } } /// /// 设置编辑标志值 /// /// public void SetEditFlag(bool state) { imageEditFlag = state; } /// /// 左标识命令功能函数 /// private void btnL_Click(object sender, RoutedEventArgs e) { //string sFontName = configInfoModel.RLMarkFontName; //int nFontSize = configInfoModel.RLMarkFontSize; string sFontName = "微软雅黑"; int nFontSize = 200; if (this.imageview.HasImage) { int X2 = this.imageview.Width - 200; int Y2 = 30; this.imageview.DrawFlag = "L"; this.imageview.AddText(X2, Y2, "L", nFontSize, sFontName); this.imageview.ProcType = KrayImgViewLib.tagPROC_TYPE.PT_NONE; this.imageview.Invalidate(); SetEditFlag(true); } } /// /// 文字标识命令功能函数 /// private void btnText_Click(object sender, RoutedEventArgs e) { string sFontName = "微软雅黑"; int nFontSize = 80; if (this.imageview.HasImage) { this.imageview.SetTextFont(sFontName, nFontSize); this.imageview.ProcType = KrayImgViewLib.tagPROC_TYPE.PT_TEXT; SetEditFlag(true); } } /// /// 清除更多命令功能函数 /// private void btnClearMore_Click(object sender, RoutedEventArgs e) { PopupEraserMoreIsOpen = true; //PopupEraserMoreIsOpen = true; } /// /// 清除所有命令功能函数 /// private void btnClearAll_Click(object sender, RoutedEventArgs e) { if (this.imageview.HasImage) { this.imageview.DeleteAnnotation(true); this.imageview.Invalidate(); SetEditFlag(true); } PopupEraserMoreIsOpen = false; } /// /// 清除所选命令功能函数 /// private void btnClearChoose_Click(object sender, RoutedEventArgs e) { if (this.imageview.HasImage) { this.imageview.DeleteAnnotation(false); this.imageview.Invalidate(); SetEditFlag(true); } PopupEraserMoreIsOpen = false; } /// /// 反白 /// /// /// private void btnInvert_Click(object sender, RoutedEventArgs e) { if (this.imageview.HasImage) { this.imageview.BlackWhite(); this.imageview.Invalidate(); SetEditFlag(true); } } /// /// 自动窗宽窗位 /// private void btnAutoWL_Click(object sender, RoutedEventArgs e) { int winWidth = WinWidth; //窗宽 int winLevel = WinLevel; //窗位 if (this.imageview.HasImage) { this.imageview.SetOptimizeWindowLevel(); this.imageview.GetWindowLevel(out winWidth, out winLevel); WinWidth = winWidth; WinLevel = winLevel; //UpdateWWWLSlider(); SetEditFlag(true); } } /// /// 窗宽改变命令初始化功能函数 /// private void SliderWWValueChangedFun() { if (this.imageview != null) { if (this.imageview.HasImage) { WinWidth = (int)this.SliderWW.Value; RefreshWWWLImageView(); } } } /// /// 窗位改变命令初始化功能函数 /// private void SliderWLValueChangedFun() { if (this.imageview != null) { if (this.imageview.HasImage) { WinLevel = (int)this.SliderWL.Value; RefreshWWWLImageView(); } } } /// /// 窗宽窗位控件值与直方图更新显示功能函数 /// private void RefreshWWWLImageView() { //判断是否有图像,当前绘画非病人信息(后面增加) if (this.imageview.HasImage) { this.imageview.SetWindowLevel(WinWidth, WinLevel); this.imageview.Invalidate(); } } /// /// 保存图像单击功能函数 /// private void btnSaveImage_Click(object sender, RoutedEventArgs e) { string msg = "保存图像"; SaveImageFun(msg); } /// /// 保存图像函数 /// private void SaveImageFun(string msg) { int imgHeight = 0; //图像高 int imgWidth = 0; //图像宽 int imgBit = 0; //图像位 int imgSize = 0; //图像大小 /*图像显示控件无图像,则返回*/ if (!this.imageview.HasImage) { //EMessageBox.Show("未选择图像或显示控件无图像!", "提示", EMessageBoxButton.OK, EMessageBoxImage.Information); System.Windows.MessageBox.Show("显示控件无图像"); SetEditFlag(false); return; } } #endregion #endregion } } 1.2、问题分析 

      仔细考虑了一下上下文,对比了https://blog.csdn.net/xpj8888/article/details/83536880,并单部执行了,发现了是参数类型的问题。Receive(Object obj)应该替换为Receive(object obj),就不会出错了。

      Object是类,而object是类型。具体的区别,可以参考https://docs.microsoft.com/en-us/dotnet/api/system.object?redirectedfrom=MSDN&view=netframework-4.8

1.3、拓展Socket的同步连接与异步连接

       针对1.1问题,我当时考虑、并调试了好久,好在终于发现问题。我一度地怀疑Socket同步与异步的问题。我是一个不言放弃、勇于探索的人。好了,现在花点时间,来学习Socket同步与异步。学习,就要举一反三。

1.3.1、什么是同步连接、异步连接

http://blog.sina.com.cn/s/blog_5d29ee450102vrfg.html

      同步连接:

      比如1.1就是一个同步通信方式,它的工作方式与阻塞优点类似。即,每个服务对象,都要开启一个线程,浪费线程资源,性能差,可接入用户数量少。(但要注意同步通信与阻塞通信不是等同的)

      异步连接:参考https://www.debugease.com/csharp/1114414.html

可接入用户较多、性能高一般用异步socket大概可以支持1000个客户端,如果需要更多的话,建议用完成端口(IOCP)。被人做过异步的通讯项目,在1500个客户端连接时,服务器端只有50个左右的线程......相当完美。对于异步Socket,连接数与线程数关系不大,与内存占用才是线性关系。https://bbs.csdn.net/topics/390510655?page=1

使用SuperSocket打造逾10万长连接的Socket服务

二、Socket同步通信实现

        同步实现,请参考1.1。或者参考下面的完整代码:

2.1、Server

MainWindow.xaml

MainWindow.xaml.cs

using Microsoft.Win32; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace Server { /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window { string Receive_IPandPort = ""; public MainWindow() { InitializeComponent(); //当点击开始监听的时候,在服务器端创建一个负责监听IP地址跟端口号的Socket Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse("127.0.0.1");//IPAddress.Any; //创建端口号对象 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); //监听 socketWatch.Bind(point); ShowMsg("监听成功"); socketWatch.Listen(10); Thread th = new Thread(Listen); th.IsBackground = true; th.Start(socketWatch); } public delegate void delegate1(string str);//定义委托 public delegate int delegate2(string endPoint); Socket Server; //将远程连接的客户端的IP地址和Socket存入集合中 Dictionary dicSocket = new Dictionary(); /// /// 等待客户端的连接,并且创建与之通信的Socket /// /// void Listen(object o) { Socket socketWatch = o as Socket; //等待客户端的连接,并且创建一个负责通信的Socket while (true) { try { //负责跟客户端通信的Socket Server = socketWatch.Accept(); //将远程连接的客户端的IP地址和Socket存入集合中 dicSocket.Add(Server.RemoteEndPoint.ToString(), Server); //将远程连接的客户端的IP地址和端口号存储下拉框中 //cboUsers.Items.Add(Server.RemoteEndPoint.ToString()); //Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate2(cboUsers.Items.Add), Server.RemoteEndPoint.ToString()); Receive_IPandPort = Server.RemoteEndPoint.ToString(); //192.168.0.100:连接成功 Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), Server.RemoteEndPoint.ToString() + ":" + "连接成功"); //开启一个新的线程,不停地接收客户端发送过来的消息 Thread th = new Thread(Receive); th.IsBackground = true; th.Start(Server); } catch { } } } /// /// 服务端不停地接收客户端发送过来的消息 /// /// void Receive(object o) { Socket Server = o as Socket; while (true) { try { //客户端连接成功后,服务器应该接收服务器应该接收客户端发来的消息 byte[] buffer = new byte[1024 * 1024 * 2]; //实际接收到的有效字节数 int r = Server.Receive(buffer); if (r == 0) { break; } else if (buffer[0] == 0) { string str = Encoding.UTF8.GetString(buffer, 1, r-1); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[接收]" + Server.RemoteEndPoint.ToString() + ":" + str); } else if (buffer[0] == 1) { string savePath; byte[] fileContext = new byte[0]; GetSavePathAndFileContextByte(buffer, out savePath, out fileContext); //读取从客户端传输过来的文件名、文件内容 System.IO.File.WriteAllBytes(savePath, fileContext);//将内容写入到制定的路径。 //MessageBox.Show("保存图片成功"); ShowImage(savePath); string fileName = System.IO.Path.GetFileName(savePath); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[接收]" + Server.RemoteEndPoint.ToString() + ":" + "接收的图片或文件:" + fileName); } else if (buffer[0] == 2) { //Shock(); } } catch { //MessageBox.Show("你接收的是非法文件或非法消息"); } } } private void ShowMsg(string str) { txtContent.AppendText(str + "\r\n"); } private void ShowImage(string path) { this.Dispatcher.BeginInvoke((Action)delegate ()//异步委托,直接更新UI线程 { //string fileName = System.IO.Path.GetFileName(path); //Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[接收]" + Client.RemoteEndPoint.ToString() + ":" + "接收的图片或文件:" + fileName); string ReceiveFileNameProperty_str = System.IO.Path.GetExtension(path); //获取后缀。 //必须判断,是图片执行,并显示。 if ((ReceiveFileNameProperty_str == ".jpg") || (ReceiveFileNameProperty_str == ".png") || (ReceiveFileNameProperty_str == ".bmp") || (ReceiveFileNameProperty_str == ".jpeg") || (ReceiveFileNameProperty_str == ".JPG") || (ReceiveFileNameProperty_str == ".PNG") || (ReceiveFileNameProperty_str == ".BMP") || (ReceiveFileNameProperty_str == ".JPEG")) { Image_PlayImage.Source = new BitmapImage(new Uri(path, UriKind.Absolute));//绝对路径 } //btn_StartServer.Content = "接收完成"; } ); } /// /// 服务器给客户端发送消息 /// /// /// private void btnSendMsg_Click(object sender, RoutedEventArgs e) { string str = txtSendMsg.Text.Trim(); byte[] buffer = Encoding.UTF8.GetBytes(str); List list = new List(); list.Add(0); list.AddRange(buffer); //将泛型集合转换为数组 byte[] newBuffer = list.ToArray(); //获得用户在下拉框中选中的IP地址 //string ip = cboUsers.SelectedItem.ToString(); //dicSocket[ip].Send(newBuffer); dicSocket[Receive_IPandPort].Send(newBuffer); txtSendMsg.Text = ""; //发送时,也要在消息显示发送的消息。 Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[发送]" + Server.RemoteEndPoint.ToString() + ":" + str); } /// /// 选择要发送的文件 /// /// /// private void btnChooseFile_Click(object sender, RoutedEventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = "C:\\Users\\Administrator\\Desktop\\Server发"; //ofd.Title = "请选择要发送的文件"; //ofd.Filter = "所有文件|*.*"; ofd.ShowDialog(); txtFilePath.Text = ofd.FileName; ShowImage(txtFilePath.Text); } private void btnSendFile_Click(object sender, RoutedEventArgs e) { string path = txtFilePath.Text;//文件的路径 string fileName = System.IO.Path.GetFileName(path); Byte[] fileNameByte = GetFileNameByte(fileName);//文件名的字节数。 Byte[] fileContentByte = GetfileContentByte(path);//文件内容。 Byte[] combomArray = GetCombomFileByte(fileNameByte, fileContentByte);//总发送的内容。 //dicSocket[cboUsers.SelectedItem.ToString()].Send(combomArray, 0, combomArray.Length, SocketFlags.None); dicSocket[Receive_IPandPort].Send(combomArray, 0, combomArray.Length, SocketFlags.None); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[发送]" + Server.RemoteEndPoint.ToString() + ":" + "已经发送图片或文件:" + fileName); } private Byte[] GetFileNameByte(string SendFileName_str) { byte[] fileNameByteVar = System.Text.Encoding.UTF8.GetBytes(SendFileName_str); return fileNameByteVar; } private Byte[] GetfileContentByte(string path) { FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);//读取文件 Byte[] fileContentByteVar = new Byte[fs.Length]; try { fs.Read(fileContentByteVar, 0, fileContentByteVar.Length); fs.Close(); //return fileContentByteVar; } catch { MessageBox.Show("获取文件内容字节失败"); //return fileContentByteVar; } return fileContentByteVar; } /// /// 四部分,第一部分为1B,区分发送类型,即指令或文件。二部分为4B,保存文件名所占的字符串长度。三部分,保存文件名的内容。四部分,文件的正式内容。 /// /// /// /// private Byte[] GetCombomFileByte(Byte[] fileNameByte, Byte[] fileContentByte) { int fileNameLong = fileNameByte.Length;//将文件的长度保存为一个整数。 byte[] fileNameLongByte = new byte[4];//将整数放在4个字节中传输。 fileNameLongByte = BitConverter.GetBytes(fileNameLong);//一个int等于四个字节。 int combomFileLong = 1 + fileNameByte.Length + fileNameLongByte.Length + fileContentByte.Length;//总字节长度 Byte[] combomFileByteTemple = new byte[combomFileLong]; for (int i = 0; i < combomFileLong; i++) { if (i == 0)//区分发送类型,即指令或文件 { combomFileByteTemple[0] = 1;// 1表示发送文件 } else if ((i > 0) && (i < (fileNameLongByte.Length + 1)))//确认文件名的长度,四个字节保存。 { combomFileByteTemple[i] = fileNameLongByte[i-1]; } else if ( (i >= (fileNameLongByte.Length + 1)) && (i < (fileNameByte.Length + fileNameLongByte.Length + 1)) )//文件名的内容 { combomFileByteTemple[i] = fileNameByte[i - fileNameLongByte.Length - 1];//从第0号位置读取fileNameByte } else { combomFileByteTemple[i] = fileContentByte[i - fileNameByte.Length - fileNameLongByte.Length - 1];//从第0号位置读取fileContentByte } } return combomFileByteTemple; } /// /// 获取文件路径path(path包含了文件夹、文件名、文明类型)、文件内容 /// /// /// /// private void GetSavePathAndFileContextByte(Byte[] fs, out string savePath, out byte[] fileContext) { string folderStr = "C:\\Users\\lanmage2\\Desktop\\Server收\\";//文件夹的位置 string fileNameStr;//从客户端传输过来的文件名 int fileNameLong = 0; byte[] fileNameLongByte = new byte[4];//固定四个字节,用来保存名字的长度。 byte[] fileNameByte = new byte[0];//初始化为0 byte[] fileContextByte = new byte[0];//初始化为0 int count = 0; while (count < fs.Length) { if (count == 0) { //不做任何处理,方便逻辑的理解 } else if ( (count > 0) && (count < 4 + 1 ) ) { fileNameLongByte[count - 1] = fs[count]; fileNameLong = BitConverter.ToInt32(fileNameLongByte, 0);//将字节转化为整数,该整数位文件名的长度。 fileNameByte = new byte[fileNameLong]; fileContextByte = new byte[fs.Length - 1 - 4 - fileNameByte.Length]; } else if ((count >= (4 + 1)) && (count < (fileNameByte.Length + 4 + 1))) { fileNameByte[count - 4 - 1] = fs[count]; } else { fileContextByte[count - (fileNameByte.Length + 4 + 1)] = fs[count]; } count++; } fileNameStr = Encoding.UTF8.GetString(fileNameByte);//将字节数组转为字符串 savePath = folderStr + fileNameStr; fileContext = fileContextByte; } private void BtnSysShutDown_Click(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } } } 2.2、Client

MainWindow.xaml

MainWindow.xaml.cs

using Microsoft.Win32; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace Server { /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window { string Receive_IPandPort = ""; public MainWindow() { InitializeComponent(); //当点击开始监听的时候,在服务器端创建一个负责监听IP地址跟端口号的Socket Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse("127.0.0.1");//IPAddress.Any; //创建端口号对象 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); //监听 socketWatch.Bind(point); ShowMsg("监听成功"); socketWatch.Listen(10); Thread th = new Thread(Listen); th.IsBackground = true; th.Start(socketWatch); } public delegate void delegate1(string str);//定义委托 public delegate int delegate2(string endPoint); Socket Server; //将远程连接的客户端的IP地址和Socket存入集合中 Dictionary dicSocket = new Dictionary(); /// /// 等待客户端的连接,并且创建与之通信的Socket /// /// void Listen(object o) { Socket socketWatch = o as Socket; //等待客户端的连接,并且创建一个负责通信的Socket while (true) { try { //负责跟客户端通信的Socket Server = socketWatch.Accept(); //将远程连接的客户端的IP地址和Socket存入集合中 dicSocket.Add(Server.RemoteEndPoint.ToString(), Server); //将远程连接的客户端的IP地址和端口号存储下拉框中 //cboUsers.Items.Add(Server.RemoteEndPoint.ToString()); //Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate2(cboUsers.Items.Add), Server.RemoteEndPoint.ToString()); Receive_IPandPort = Server.RemoteEndPoint.ToString(); //192.168.0.100:连接成功 Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), Server.RemoteEndPoint.ToString() + ":" + "连接成功"); //开启一个新的线程,不停地接收客户端发送过来的消息 Thread th = new Thread(Receive); th.IsBackground = true; th.Start(Server); } catch { } } } /// /// 服务端不停地接收客户端发送过来的消息 /// /// void Receive(object o) { Socket Server = o as Socket; while (true) { try { //客户端连接成功后,服务器应该接收服务器应该接收客户端发来的消息 byte[] buffer = new byte[1024 * 1024 * 2]; //实际接收到的有效字节数 int r = Server.Receive(buffer); if (r == 0) { break; } else if (buffer[0] == 0) { string str = Encoding.UTF8.GetString(buffer, 1, r-1); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[接收]" + Server.RemoteEndPoint.ToString() + ":" + str); } else if (buffer[0] == 1) { string savePath; byte[] fileContext = new byte[0]; GetSavePathAndFileContextByte(buffer, out savePath, out fileContext); //读取从客户端传输过来的文件名、文件内容 System.IO.File.WriteAllBytes(savePath, fileContext);//将内容写入到制定的路径。 //MessageBox.Show("保存图片成功"); ShowImage(savePath); string fileName = System.IO.Path.GetFileName(savePath); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[接收]" + Server.RemoteEndPoint.ToString() + ":" + "接收的图片或文件:" + fileName); } else if (buffer[0] == 2) { //Shock(); } } catch { //MessageBox.Show("你接收的是非法文件或非法消息"); } } } private void ShowMsg(string str) { txtContent.AppendText(str + "\r\n"); } private void ShowImage(string path) { this.Dispatcher.BeginInvoke((Action)delegate ()//异步委托,直接更新UI线程 { //string fileName = System.IO.Path.GetFileName(path); //Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[接收]" + Client.RemoteEndPoint.ToString() + ":" + "接收的图片或文件:" + fileName); string ReceiveFileNameProperty_str = System.IO.Path.GetExtension(path); //获取后缀。 //必须判断,是图片执行,并显示。 if ((ReceiveFileNameProperty_str == ".jpg") || (ReceiveFileNameProperty_str == ".png") || (ReceiveFileNameProperty_str == ".bmp") || (ReceiveFileNameProperty_str == ".jpeg") || (ReceiveFileNameProperty_str == ".JPG") || (ReceiveFileNameProperty_str == ".PNG") || (ReceiveFileNameProperty_str == ".BMP") || (ReceiveFileNameProperty_str == ".JPEG")) { Image_PlayImage.Source = new BitmapImage(new Uri(path, UriKind.Absolute));//绝对路径 } //btn_StartServer.Content = "接收完成"; } ); } /// /// 服务器给客户端发送消息 /// /// /// private void btnSendMsg_Click(object sender, RoutedEventArgs e) { string str = txtSendMsg.Text.Trim(); byte[] buffer = Encoding.UTF8.GetBytes(str); List list = new List(); list.Add(0); list.AddRange(buffer); //将泛型集合转换为数组 byte[] newBuffer = list.ToArray(); //获得用户在下拉框中选中的IP地址 //string ip = cboUsers.SelectedItem.ToString(); //dicSocket[ip].Send(newBuffer); dicSocket[Receive_IPandPort].Send(newBuffer); txtSendMsg.Text = ""; //发送时,也要在消息显示发送的消息。 Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[发送]" + Server.RemoteEndPoint.ToString() + ":" + str); } /// /// 选择要发送的文件 /// /// /// private void btnChooseFile_Click(object sender, RoutedEventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = "C:\\Users\\Administrator\\Desktop\\Server发"; //ofd.Title = "请选择要发送的文件"; //ofd.Filter = "所有文件|*.*"; ofd.ShowDialog(); txtFilePath.Text = ofd.FileName; ShowImage(txtFilePath.Text); } private void btnSendFile_Click(object sender, RoutedEventArgs e) { string path = txtFilePath.Text;//文件的路径 string fileName = System.IO.Path.GetFileName(path); Byte[] fileNameByte = GetFileNameByte(fileName);//文件名的字节数。 Byte[] fileContentByte = GetfileContentByte(path);//文件内容。 Byte[] combomArray = GetCombomFileByte(fileNameByte, fileContentByte);//总发送的内容。 //dicSocket[cboUsers.SelectedItem.ToString()].Send(combomArray, 0, combomArray.Length, SocketFlags.None); dicSocket[Receive_IPandPort].Send(combomArray, 0, combomArray.Length, SocketFlags.None); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new delegate1(ShowMsg), "[发送]" + Server.RemoteEndPoint.ToString() + ":" + "已经发送图片或文件:" + fileName); } private Byte[] GetFileNameByte(string SendFileName_str) { byte[] fileNameByteVar = System.Text.Encoding.UTF8.GetBytes(SendFileName_str); return fileNameByteVar; } private Byte[] GetfileContentByte(string path) { FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);//读取文件 Byte[] fileContentByteVar = new Byte[fs.Length]; try { fs.Read(fileContentByteVar, 0, fileContentByteVar.Length); fs.Close(); //return fileContentByteVar; } catch { MessageBox.Show("获取文件内容字节失败"); //return fileContentByteVar; } return fileContentByteVar; } /// /// 四部分,第一部分为1B,区分发送类型,即指令或文件。二部分为4B,保存文件名所占的字符串长度。三部分,保存文件名的内容。四部分,文件的正式内容。 /// /// /// /// private Byte[] GetCombomFileByte(Byte[] fileNameByte, Byte[] fileContentByte) { int fileNameLong = fileNameByte.Length;//将文件的长度保存为一个整数。 byte[] fileNameLongByte = new byte[4];//将整数放在4个字节中传输。 fileNameLongByte = BitConverter.GetBytes(fileNameLong);//一个int等于四个字节。 int combomFileLong = 1 + fileNameByte.Length + fileNameLongByte.Length + fileContentByte.Length;//总字节长度 Byte[] combomFileByteTemple = new byte[combomFileLong]; for (int i = 0; i < combomFileLong; i++) { if (i == 0)//区分发送类型,即指令或文件 { combomFileByteTemple[0] = 1;// 1表示发送文件 } else if ((i > 0) && (i < (fileNameLongByte.Length + 1)))//确认文件名的长度,四个字节保存。 { combomFileByteTemple[i] = fileNameLongByte[i-1]; } else if ( (i >= (fileNameLongByte.Length + 1)) && (i < (fileNameByte.Length + fileNameLongByte.Length + 1)) )//文件名的内容 { combomFileByteTemple[i] = fileNameByte[i - fileNameLongByte.Length - 1];//从第0号位置读取fileNameByte } else { combomFileByteTemple[i] = fileContentByte[i - fileNameByte.Length - fileNameLongByte.Length - 1];//从第0号位置读取fileContentByte } } return combomFileByteTemple; } /// /// 获取文件路径path(path包含了文件夹、文件名、文明类型)、文件内容 /// /// /// /// private void GetSavePathAndFileContextByte(Byte[] fs, out string savePath, out byte[] fileContext) { string folderStr = "C:\\Users\\lanmage2\\Desktop\\Server收\\";//文件夹的位置 string fileNameStr;//从客户端传输过来的文件名 int fileNameLong = 0; byte[] fileNameLongByte = new byte[4];//固定四个字节,用来保存名字的长度。 byte[] fileNameByte = new byte[0];//初始化为0 byte[] fileContextByte = new byte[0];//初始化为0 int count = 0; while (count < fs.Length) { if (count == 0) { //不做任何处理,方便逻辑的理解 } else if ( (count > 0) && (count < 4 + 1 ) ) { fileNameLongByte[count - 1] = fs[count]; fileNameLong = BitConverter.ToInt32(fileNameLongByte, 0);//将字节转化为整数,该整数位文件名的长度。 fileNameByte = new byte[fileNameLong]; fileContextByte = new byte[fs.Length - 1 - 4 - fileNameByte.Length]; } else if ((count >= (4 + 1)) && (count < (fileNameByte.Length + 4 + 1))) { fileNameByte[count - 4 - 1] = fs[count]; } else { fileContextByte[count - (fileNameByte.Length + 4 + 1)] = fs[count]; } count++; } fileNameStr = Encoding.UTF8.GetString(fileNameByte);//将字节数组转为字符串 savePath = folderStr + fileNameStr; fileContext = fileContextByte; } private void BtnSysShutDown_Click(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } } } 三、Socket异步通信实现

       请参考 https://www.cnblogs.com/liuyong/archive/2011/09/08/1892217.html

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3