这里主要写 PC 服务器端的逻辑,UI 使用的是 WPF,因为 WPF 比普通的 WinForm 的流式布局

更容易控制,而且比 WinForm 美观一些,显示截图:

一、页面 UI

MainWindow.xaml 文件中布局的 XAML:

   <Grid ShowGridLines="True"><Grid.Resources><Style TargetType="Button"><Setter Property="Width" Value="110"/><Setter Property="Height" Value="30"/><Setter Property="Margin" Value="10,0,10,0"/></Style></Grid.Resources><Grid.ColumnDefinitions><ColumnDefinition Width="80*"/><ColumnDefinition Width="20*"/></Grid.ColumnDefinitions><Grid ShowGridLines="True"><Grid.RowDefinitions><RowDefinition Height="1*"/><RowDefinition Height="7*"/><RowDefinition Height="2*"/></Grid.RowDefinitions><!--本地 IP--><StackPanel Orientation="Horizontal"><StackPanel.Resources><Style TargetType="TextBlock"><Setter Property="Width" Value="120"/><Setter Property="VerticalAlignment" Value="Center"/><Setter Property="HorizontalAlignment" Value="Center"/></Style></StackPanel.Resources><!--服务器端的 IP 和端口号--><TextBlock x:Name="txtIP" Margin="4,14,0,14" Width="144"/><TextBlock x:Name="txtPort" Text="5000" Margin="10, 0, 0, 0"/><Button x:Name="btnBeginListening" Content="开始侦听" HorizontalAlignment="Right" Click="btnBeginListening_Click"/><!--<Button x:Name="btnStop" Content="停止" HorizontalAlignment="Right" Click="btnStop_Click"/>--></StackPanel><!--消息窗口和消息发送窗口--><Grid Grid.Row="1"><Grid.RowDefinitions><RowDefinition Height="8*"/><RowDefinition Height="2*"/></Grid.RowDefinitions><ScrollViewer x:Name="scroll"><!--显示连接状态、聊天消息等--><TextBlock x:Name="txtResult"  TextWrapping="Wrap"/></ScrollViewer><!--聊天文字输入框--><TextBox x:Name="txtInput" Grid.Row="1" KeyDown="txtInput_KeyDown" TextWrapping="Wrap"/></Grid><!--操作按钮--><Grid Grid.Row="2"><Grid.ColumnDefinitions><ColumnDefinition Width="5*"/><ColumnDefinition Width="5*"/></Grid.ColumnDefinitions><StackPanel Orientation="Horizontal"><!--用户选择的文件的路径--><TextBox x:Name="txtFilePath" Width="150" Height="40"/><Button Content="选择文件" x:Name="btnChooseFile" Click="btnChooseFile_Click"/></StackPanel><StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Grid.Column="1"><!--发送文件或者发送文字消息--><Button Content="发送文件" x:Name="btnSendFile" Click="btnSendFile_Click"/><Button Content="发送消息" x:Name="btnSendMsg" Click="btnSendMsg_Click"/></StackPanel></Grid></Grid><!--显示请求连接到服务器端的 WP 端的 IP 信息--><ListBox Grid.Column="1" x:Name="listbox"></ListBox></Grid>

二、定义一个服务器端的 SocketClient 类,用来封装与 WP 端通讯所使用的 Socket

虽然 WP 和 PC 端都是使用 C# 语言开发的,但是 WP 端和 PC 端的 Socket 类在使用方法上有一些差异,

并且 WP 端明显是经过精简过的,这里就不贴出来了。直接贴出 SocketClient 类:

namespace DesktopSocketServerDemo
{/// <summary>/// 与客户端的 连接通信类(包含了一个 与客户端 通信的 套接字,和线程)/// </summary>public class SocketClient{Socket sokMsg;Thread threadMsg;// 通信操作完成时调用,用来触发在操作完成时,在宿主页面显示消息提示public event EventHandler<string> Completed;public SocketClient(Socket sokMsg){this.sokMsg = sokMsg;this.threadMsg = new Thread(ReceiveMsg);this.threadMsg.IsBackground = true;this.threadMsg.Start();}bool isRec = true;// 负责监听客户端发送来的消息void ReceiveMsg(){while (isRec){try{byte[] byteSrc = new byte[CommonHelper.FileLength];// 从绑定的 Socket 套接字接收数据,将数据存入接收缓冲区。int length = sokMsg.Receive(byteSrc);DataType dataType;byte[] bytesFile;string strMsg;// 转换源 byte[] 数据内容,获取其中的 head 和 body 的实际内容CommonHelper.ConvertByteToData(byteSrc, out dataType, out bytesFile, out strMsg);if (dataType.IsFile == true){// 如果 body 的类型文件,则直接将文件存储到 PC 端的 D: 盘根路径下using (FileStream file = new FileStream("d:\\" + dataType.FileName + dataType.Exten, FileMode.OpenOrCreate)){file.Write(bytesFile, 0, bytesFile.Length);}// 显示回调消息OnCompleted("客户端发送的文件:" + dataType.FileName + dataType.Exten);OnCompleted("该文件保存在 D: 盘的根目录下");}else{OnCompleted(">>客户端:" + strMsg);}}catch (Exception ex){// 如果抛异常,则释放该 Socket 对象所占用的资源
                    CloseConnection();OnCompleted("SocketClient.ReceiveMsg() :" + ex.Message);}}}/// <summary>   ///  向客户端发送消息   /// </summary>/// <param name="strMsg"></param>public void Send(string strMsg){byte[] arrMsgFinal = CommonHelper.ConvertDataToByte(new DataType { IsFile = false }, null, strMsg);sokMsg.Send(arrMsgFinal);}// 向客户端发送文件数据public void SendFile(string strPath){try{byte[] arrFileFina = CommonHelper.ConvertDataToByte(new DataType { IsFile = true }, strPath, null);//发送文件数据sokMsg.Send(arrFileFina);//, 0, length + 1, SocketFlags.None);OnCompleted("发送文件完成");}catch (Exception ex){OnCompleted(ex.Message);}}// 关闭与客户端连接public void CloseConnection(){isRec = false;sokMsg.Close();sokMsg.Dispose();}void OnCompleted(string strMsg){if (Completed != null){Completed(null, strMsg);}}}
}

三、在 MainWindow.xaml 文件中,定义侦听客户端连接的 Socket

MainWindow.xaml 文件相应的 Codebehind 代码:

namespace DesktopSocketServerDemo
{/// <summary>/// PC 端服务器,用来接收连接 PC 的 Socket 连接,并创建 SocketClient 类与客户端通信/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();//MultiCast cast = new MultiCast();//cast.Startup();
txtIP.Text += "本地 IP:" + strIP;txtPort.Text = " 端口:" + Port;}int Port = 5000;// 服务器端的 IP 地址string strIP = CommonHelper.GetIPAddress();//负责监听 客户端 的连接请求Socket socketWatch = null;// 执行 socketWatch 对象监听请求的线程Thread threadWatch = null; // 开启监听private void btnBeginListening_Click(object sender, RoutedEventArgs e){if (socketWatch == null){//实例化 套接字 (ip4寻址协议,流式传输,TCP协议)socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(strIP), Port);//将 监听套接字  绑定到 对应的IP和端口
                socketWatch.Bind(endpoint);//设置 监听队列 长度为10(同时能够处理 10个连接请求)socketWatch.Listen(10);threadWatch = new Thread(StartWatch);threadWatch.IsBackground = true;threadWatch.Start();ShowMsg("启动服务器成功......\r\n");}else{ShowMsg("服务器已经启动");}}// 循环侦听客户端的连接请求bool isWatch = true;// 负责与客户端通信的对象
        SocketClient socketClient;/// <summary>/// 被线程调用 监听连接端口/// </summary>void StartWatch(){while (isWatch){try{//监听 客户端 连接请求,但是,Accept会阻断当前线程//监听到请求,立即创建负责与该客户端套接字通信的套接字Socket socket = socketWatch.Accept();if (socketClient != null)socketClient.CloseConnection();socketClient = new SocketClient(socket);socketClient.Completed += connection_Completed;this.Dispatcher.BeginInvoke(new Action(delegate{if (socket != null && socket.RemoteEndPoint != null)//将 通信套接字的 客户端IP端口保存在下拉框里listbox.Items.Add(new TextBlock { Text = socket.RemoteEndPoint.ToString() });ShowMsg("接收一个客户端连接......");}), null);}catch (Exception ex){ShowMsg(ex.Message);socketWatch.Close();socketWatch.Dispose();isWatch = false;}}}//发送消息到已经连接到 PC 的客户端private void btnSendMsg_Click(object sender, EventArgs e){if (string.IsNullOrEmpty(txtInput.Text)){ShowMsg("输入内容不能为空");return;}if (socketClient != null){ShowMsg(txtInput.Text.Trim());// 发送文字内容
                socketClient.Send(txtInput.Text.Trim());txtInput.Text = "";}else{MessageBox.Show("还没有建立连接");}}//选择要发送的文件private void btnChooseFile_Click(object sender, EventArgs e){Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();if (openFileDialog.ShowDialog() == true){txtFilePath.Text = openFileDialog.FileName;}}//发送文件private void btnSendFile_Click(object sender, EventArgs e){if (string.IsNullOrWhiteSpace(txtFilePath.Text)){MessageBox.Show("请先选择一个文件");return;}//connection = new SocketClient();if (socketClient != null){// 发送文件内容
                socketClient.SendFile(txtFilePath.Text.Trim());}else{MessageBox.Show("还没有建立连接");}}// 操作完成void connection_Completed(object sender, string e){ShowMsg(e);}// 向窗口追加消息void ShowMsg(string strMsg){this.Dispatcher.BeginInvoke(new Action(delegate{txtResult.Text += Environment.NewLine + strMsg + Environment.NewLine;scroll.ScrollToBottom();}), null);}// 当服务器关闭时触发protected override void OnClosed(EventArgs e){if (socketWatch != null){socketWatch.Close();socketWatch.Dispose();}base.OnClosed(e);}// 按“回车键”发送消息private void txtInput_KeyDown(object sender, KeyEventArgs e){if (e.Key == Key.Enter){btnSendMsg_Click(null, null);}}// 释放连接资源//private void btnStop_Click(object sender, RoutedEventArgs e)//{//    if (socketClient != null)//    {//        socketClient.CloseConnection();//    }//    if (sokWatch != null)//    {//        sokWatch.Close();//        sokWatch.Dispose();//    }//}
    }
}

转载于:https://www.cnblogs.com/hebeiDGL/p/3155255.html

02、Windows Phone 套接字(Socket)实战之服务器端设计相关推荐

  1. Windows套接字(Socket)例子(源码,实例)

    最简单的Windows套接字(Socket)例子(源码,实例) 佟强(http://blog.csdn.net/microtong) 2008年11月21日 Server.exe PortNumber ...

  2. Windows 网络通信套接字技术

    文章目录 一.TCP/IP介绍 1.TCP/IP体系结构 2.TCP/IP特点 3.TCP/IP协议与WinSock网络编程接口的关系 二.套接字原理 1.客户机/服务器模式 服务器端: 客户端: 2 ...

  3. Linux下套接字详解(二)----套接字Socket

    在前面我们讲了TCP/IP.TCP和UDP的一些基本知识,但是协议只有一套,而我们系统多个TCP连接或多个应用程序进程必须通过同一个 TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计算 ...

  4. Windows下套接字

    一.套接字     windows套接字Socket是进程通信的一种方式,可以实现在不同主机的相关进程之间交换数据.在TCP/IP网络应用中,通信的两个进程的主要模式是客户/服务器(C/S)模式,即客 ...

  5. 5.1 计算机网络之传输层(传输层提供的服务及功能概述、端口、套接字--Socket、无连接UDP和面向连接TCP服务)

    文章目录 1.传输层提供的服务及功能概述 2.传输层的寻址与端口 (1)端口的作用 (2)端口号的分类 (3)套接字 3.无连接UDP和面向连接TCP服务 1.传输层提供的服务及功能概述 传输层的功能 ...

  6. [python学习] 专题七.网络编程之套接字Socket、TCP和UDP通信实例

    很早以前研究过C#和C++的网络通信,参考我的文章:                  C#网络编程之Tcp实现客户端和服务器聊天                 C#网络编程之套接字编程基础知识   ...

  7. Java 套接字Socket

    套接字 一.概述 本质上是一套基于网络传输数据的流 实际上是一套用于网络通信的API IP地址 IPv4是指由4组数组成的IP地址 , 每组数的范围在0~255 .一共有2的32次方个地址(43亿多) ...

  8. Java套接字Socket编程--TCP参数

    在Java的Socket中,主要包含了以下可设置的TCP参数. 属性 说明 默认值 SO_TIMEOUT 对ServerSocket来说表示等待连接的最长空等待时间; 对Socket来说表示读数据最长 ...

  9. 套接字socket 的地址族和类型、工作原理、创建过程

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

最新文章

  1. 天才也勤奋!DeepMind哈萨比斯自述:领导400名博士向前,每天工作至凌晨4点
  2. Python-time
  3. 技术人员写blog的好处
  4. 红黑树的删除_Python实现红黑树的删除操作
  5. leetcode combinations java_[LeetCode][Java] Combinations
  6. mysql控制台导出查询结果_MySQL 命令行导出、导入Select 查询结果
  7. 421. 数组中两个数的最大异或值
  8. java分布式-一致性
  9. 译:25个面试中最常问的问题和答案
  10. 越南大老二,游戏规则说明
  11. 示波器探头各种作用及工作原理,你都理解清楚了吗?
  12. Spug“账户已被系统禁用”的解决办法
  13. ios开发愤怒的小鸟的Lua语言:Wax框架详解
  14. 发一个笔筒式的摄像头驱动(台湾原相科技)
  15. Java常用术语解释
  16. (转)WAVE PCM 声音文件格式
  17. jquery开发公众号素材管理页面
  18. 第十五篇:UE4 漫游Matinee的制作和如何在漫游中实现自由转向(改进)
  19. graythresh
  20. 2020年超级计算机排名,2020中国高性能计算机TOP100榜单正式发布

热门文章

  1. R-CNN 物体检测第一弹
  2. linus开启snmp_【snmp】Linux开启snmp及查询
  3. android 获取sd卡目录失败_获取sd卡存储路径失败
  4. 设计一个扩展自抽象类geometricobject的新的triangle类_如何进行代码抽象设计?
  5. 茂名2021高考成绩查询入口,茂名高考成绩查询入口
  6. Android和iPhone应用程序界面布局示例
  7. jQuery获取cookie
  8. C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表
  9. Python lambda函数
  10. 关于“只有静态常量整型数据成员才可以在类中初始化”