博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
异步Socket服务器与客户端
阅读量:4648 次
发布时间:2019-06-09

本文共 8164 字,大约阅读时间需要 27 分钟。

本文灵感来自 在CodeProject上面的一片文章,,讲的是异步的Socket通信。

关于技术博客,我觉得永远是老外的比较好~的这篇文章里,给出了一个很复杂的例子,内容涉及如下

  • Socket连接(Socket Connection)
  • Socket服务(Socket Service)
  • 连接主机(Connection Host)
  • 加密与压缩(Encrypt与Compress)
  • 请求入队(Enqueuing Requests)
  • 确保发送和接收(Ensure send and recieve)
  • 检查消息头(Check message header)
  • 检查空闲连接(Checking idle connections)
  • 加密服务
  • SSL认证(SSL authentication)
  • 对称认证(Symmetric authentication)
  • 连接创建者(Connection Creator)
  • Socket服务器与Socket侦听者(SocketServer and SocketListener)
  • Socket服务器构造函数与方法(SocketServer constructor and methods)
  • Socket客户端与Socket连接者(SocketClient and SocketConnector)
  • Socket客户端构造函数与方法(SocketClient constructor and methods)
  • 应答演示项目(Echo Demo Project)
  • 主机(Hosts)
  • 服务(Services)
  • 结语(Conclusion)
  • 版本历史(History)

本文仅实现一个相对简单的异步Socket服务器与客户端通信示例。

首先需要说明如下2个问题

1.同步、异步、多线程是什么关系?答:同步是等待返回,相当于阻塞式;异步是不等待返回,是非阻塞式,可以用多线程实现。

2.有些异步方法有两种实现方式, 如BeginAccept()和AcceptAsync(), 这两个方法有什么区别呢?答:  以 Begin 和 End 开头的方法是以 APM(Asynchronous Programming Model)设计方法实现的异步操作, 以 Async 结尾的方法是利用称为 EAP (Event-based Asynchronous Pattern) 的设计方法实现的异步操作。

界面简单如下:

主要代码如下:

using System;using System.Net;using System.Net.Sockets;using System.Text;namespace Chatting{    public abstract class SocketFunc    {        //不管是服务端还是客户端, 建立连接后用这个Socket进行通信        public Socket communicateSocket = null;        //服务端和客户端建立连接的方式稍有不同, 子类会重载        public abstract void Access(string IP, System.Action AccessAciton);        //发送消息的函数        public void Send(string message)        {            if (communicateSocket.Connected == false)            {                throw new Exception("还没有建立连接, 不能发送消息");            }            Byte[] msg = Encoding.UTF8.GetBytes(message);            communicateSocket.BeginSend(msg,0, msg.Length, SocketFlags.None,                ar => {                                }, null);        }        //接受消息的函数        public void Receive(System.Action
ReceiveAction) { //如果消息超过1024个字节, 收到的消息会分为(总字节长度/1024 +1)条显示 Byte[] msg = new byte[1024]; //异步的接受消息 communicateSocket.BeginReceive(msg, 0, msg.Length, SocketFlags.None, ar => { //对方断开连接时, 这里抛出Socket Exception //An existing connection was forcibly closed by the remote host communicateSocket.EndReceive(ar); ReceiveAction(Encoding.UTF8.GetString(msg).Trim('\0',' ')); Receive(ReceiveAction); }, null); } } public class ServerSocket:SocketFunc { //服务端重载Access函数 public override void Access(string IP, System.Action AccessAciton) { Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //本机预使用的IP和端口 IPEndPoint serverIP = new IPEndPoint(IPAddress.Any, 9050); //绑定服务端设置的IP serverSocket.Bind(serverIP); //设置监听个数 serverSocket.Listen(1); //异步接收连接请求 serverSocket.BeginAccept(ar => { base.communicateSocket = serverSocket.EndAccept(ar); AccessAciton(); }, null); } } public class ClientSocket:SocketFunc { //客户端重载Access函数 public override void Access(string IP, System.Action AccessAciton) { base.communicateSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); base.communicateSocket.Bind(new IPEndPoint(IPAddress.Any, 9051)); //服务器的IP和端口 IPEndPoint serverIP; try { serverIP = new IPEndPoint(IPAddress.Parse(IP), 9050); } catch { throw new Exception(String.Format("{0}不是一个有效的IP地址!", IP)); } //客户端只用来向指定的服务器发送信息,不需要绑定本机的IP和端口,不需要监听 try { base.communicateSocket.BeginConnect(serverIP, ar => { AccessAciton(); }, null); } catch { throw new Exception(string.Format("尝试连接{0}不成功!", IP)); } } }}

相关的事件处理程序,如下:

View Code
using System;using System.Drawing;using System.Windows.Forms;using System.Net.Sockets;namespace Chatting{    public partial class MainForm : Form    {        public MainForm()        {            InitializeComponent();        }        SocketFunc socket;        System.Action
ReceiveAction; System.Action AccessAction; private void MainForm_Load(object sender, EventArgs e) { //异步建立连接回调 AccessAction = () => { this.Invoke((MethodInvoker)delegate() { lblFriendIP.Visible = false; txtIP.Visible = false; btnConnect.Visible = false; btnWaitAccess.Visible = false; String friendIP = socket.communicateSocket.RemoteEndPoint.ToString(); lblState.Text = String.Format("连接成功. 对方IP:{0}", friendIP); try { socket.Receive(ReceiveAction); } catch (Exception exp) { MessageBox.Show(exp.Message, "错误"); } }); }; //异步接收消息回调 ReceiveAction = msg => { txtGetMsg.Invoke((MethodInvoker)delegate() { UpdateGetMsgTextBox(false, msg, Color.Red); }); }; } private void btnWaitAccess_Click(object sender, EventArgs e) { this.socket = new ServerSocket(); try { this.socket.Access("", this.AccessAction); } catch (Exception ecp) { MessageBox.Show(ecp.Message, "错误"); } lblState.Text = "等待对方连接..."; } private void btnConnect_Click(object sender, EventArgs e) { this.socket = new ClientSocket(); try { this.socket.Access(txtIP.Text, this.AccessAction); } catch (Exception ecp) { MessageBox.Show(ecp.Message, "错误"); } lblState.Text = "正在连接对方..."; } private void btnSendMsg_Click(object sender, EventArgs e) { string message = txtSendMsg.Text.Trim(); if (string.IsNullOrEmpty(message)) { MessageBox.Show("消息内容不能为空!", "错误"); txtSendMsg.Focus(); return; } try { socket.Send(message); } catch(Exception ecp) { MessageBox.Show(ecp.Message, "错误"); return; } UpdateGetMsgTextBox(true, message, Color.Blue); txtSendMsg.Text = ""; } private void UpdateGetMsgTextBox(bool sendMsg, string message, Color color) { string appendText; if (sendMsg == true) { appendText = "Client: " + System.DateTime.Now.ToString() + Environment.NewLine + message + Environment.NewLine; } else { appendText = "Server: " + System.DateTime.Now.ToString() + Environment.NewLine + message + Environment.NewLine; } int txtGetMsgLength = txtGetMsg.Text.Length; txtGetMsg.AppendText(appendText); txtGetMsg.Select(txtGetMsgLength, appendText.Length - Environment.NewLine.Length*2 -message.Length); txtGetMsg.SelectionColor = color; txtGetMsg.ScrollToCaret(); } private void txtSendMsg_Click(object sender, EventArgs e) { SetStyle(ControlStyles.SupportsTransparentBackColor, true); BackColor = Color.FromArgb(50, 40, 60, 82); } }}

 

效果,如下:

 

转载于:https://www.cnblogs.com/DebugLZQ/archive/2012/05/18/2508002.html

你可能感兴趣的文章
自己的一些简要学习点
查看>>
HTPJ 1268 GCD
查看>>
hdu2063 匈牙利算法 二分最大匹配模版题
查看>>
工作中的一些经验小结
查看>>
百度地图JavaScript API如何在同一页面显示多个地图?
查看>>
揭秘快速提升alexa排名的18种有效方法-2 -#来秀美#
查看>>
计算机专业及软件开发推荐书籍
查看>>
《Java程序设计》 课程教学
查看>>
Lambda--持续学习中
查看>>
简单谈谈面向对象和面向过程的区别
查看>>
Intellij IDEA 配置Tomcat远程调试
查看>>
python3 进程和线程(一)
查看>>
python-综合练习题(if条件语句,while循环,奇数偶数
查看>>
C语言基础-第三章
查看>>
PowerDesigner教程系列(一)概念数据模型
查看>>
python常用类库总结
查看>>
题解 CF962C 【Make a Square】
查看>>
只读数据文件损坏恢复
查看>>
k8s集群上线web静态网站
查看>>
【转】Impala和Hive的关系
查看>>