C# Socket系列二 简单的创建 socket 通信
看了系列一 我们开启了对socket tcp的监听状态,那么这一章我们来讲解怎么创建socket的通信代码
我新建一个类 TSocketBase
public abstract class TSocketBase { //封装socket internal Socket _Socket; //回调 private AsyncCallback aCallback; //接受数据的缓冲区 private byte[] Buffers; //标识是否已经释放 private volatile bool IsDispose; //10K的缓冲区空间 * ; //收取消息状态码 private SocketError ReceiveError; //发送消息的状态码 private SocketError SenderError; //每一次接受到的字节数 ; //接受空消息次数 ; public abstract void Receive(byte[] rbuff); public void SetSocket() { this.aCallback = new AsyncCallback(this.ReceiveCallback); this.IsDispose = false; this._Socket.ReceiveBufferSize = this.BufferSize; this._Socket.SendBufferSize = this.BufferSize; this.Buffers = new byte[this.BufferSize]; } /// <summary> /// 关闭并释放资源 /// </summary> /// <param name="msg"></param> public void Close(string msg) { if (!this.IsDispose) { this.IsDispose = true; try { try { this._Socket.Close(); } catch { } IDisposable disposable = this._Socket; if (disposable != null) { disposable.Dispose(); } this.Buffers = null; GC.SuppressFinalize(this); } catch (Exception) { } } } /// <summary> /// 递归接收消息方法 /// </summary> internal void ReceiveAsync() { try { if (!this.IsDispose && this._Socket.Connected) { , this.BufferSize, SocketFlags.None, out SenderError, this.aCallback, this); CheckSocketError(ReceiveError); } } catch (System.Net.Sockets.SocketException) { this.Close("链接已经被关闭"); } catch (System.ObjectDisposedException) { this.Close("链接已经被关闭"); } } /// <summary> /// 接收消息回调函数 /// </summary> /// <param name="iar"></param> private void ReceiveCallback(IAsyncResult iar) { if (!this.IsDispose) { try { //接受消息 ReceiveSize = _Socket.EndReceive(iar, out ReceiveError); //检查状态码 if (!CheckSocketError(ReceiveError) && SocketError.Success == ReceiveError) { //判断接受的字节数 ) { byte[] rbuff = new byte[ReceiveSize]; Array.Copy(this.Buffers, rbuff, ReceiveSize); this.Receive(rbuff); //重置连续收到空字节数 ZeroCount = ; //继续开始异步接受消息 ReceiveAsync(); } else { ZeroCount++; ) { this.Close("错误链接"); } } } } catch (System.Net.Sockets.SocketException) { this.Close("链接已经被关闭"); } catch (System.ObjectDisposedException) { this.Close("链接已经被关闭"); } } } /// <summary> /// 错误判断 /// </summary> /// <param name="socketError"></param> /// <returns></returns> bool CheckSocketError(SocketError socketError) { switch ((socketError)) { case SocketError.SocketError: case SocketError.VersionNotSupported: case SocketError.TryAgain: case SocketError.ProtocolFamilyNotSupported: case SocketError.ConnectionAborted: case SocketError.ConnectionRefused: case SocketError.ConnectionReset: case SocketError.Disconnecting: case SocketError.HostDown: case SocketError.HostNotFound: case SocketError.HostUnreachable: case SocketError.NetworkDown: case SocketError.NetworkReset: case SocketError.NetworkUnreachable: case SocketError.NoData: case SocketError.OperationAborted: case SocketError.Shutdown: case SocketError.SystemNotReady: case SocketError.TooManyOpenSockets: this.Close(socketError.ToString()); return true; } return false; } /// <summary> /// 发送消息方法 /// </summary> internal int SendMsg(byte[] buffer) { ; try { if (!this.IsDispose) { size = , buffer.Length, SocketFlags.None, out SenderError); CheckSocketError(SenderError); } } catch (System.ObjectDisposedException) { this.Close("链接已经被关闭"); } catch (System.Net.Sockets.SocketException) { this.Close("链接已经被关闭"); } buffer = null; return size; } }
上面我们事先了socket的异步接受消息,和同步发送消息已经关闭释放资源代码
接受消息net底层提供的接受消息的方法有很多,为什么我们要选择上面所写的呢?那是为了兼容U3D,silverlight, wpf, wp, wf,等程序可执行,不在重复做相同工作。
现在我们来创建一个实现类 TSocketClient
public class TSocketClient : TSocketBase { /// <summary> /// 是否是服务器端的资源 /// </summary> bool isServer = false; /// <summary> /// 客户端主动请求服务器 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> ) { isServer = false; this._Socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._Socket.Connect(ip, port); this.SetSocket(); this.ReceiveAsync(); } /// <summary> /// 这个是服务器收到有效链接初始化 /// </summary> /// <param name="socket"></param> public TSocketClient(Socket socket) { isServer = true; this._Socket = socket; this.SetSocket(); this.ReceiveAsync(); } /// <summary> /// 收到消息后 /// </summary> /// <param name="rbuff"></param> public override void Receive(byte[] rbuff) { Console.WriteLine("Receive Msg:" + System.Text.UTF8Encoding.Default.GetString(rbuff)); if (isServer) { this.SendMsg(System.Text.UTF8Encoding.Default.GetBytes("Holle Client!")); } } }
因为是测试示例,所以我把服务器和客户端实现类写成了,只是用来不同的构造函数来区分,是客户端还是服务器的标识
接下来我们测试一下代码
class Program { static void Main(string[] args) { TCPListener tcp = new TCPListener(); TSocketClient client = new TSocketClient(); client.SendMsg(System.Text.UTF8Encoding.Default.GetBytes("Holle Server!")); Console.ReadLine(); } }
运行结果看出,我们连接成功并且发送消息成功。
C# Socket系列二 简单的创建 socket 通信的更多相关文章
- C# Socket系列一 简单的创建socket的监听
socket的应用场景,在快速,稳定,保持长连接的数据传输代码.Http也是socket封装出来的,基于一次请求一次回复,然后断开的socket连接封装. 比如我们常见的游戏服务器,目前的很火的物联网 ...
- LINQ to Sql系列二 简单查询和联接查询
这一篇文章主要总结LINQ to sql的简单查询(单表查询)和联接查询(多表查询) 单表查询 需求是我们要输出TClass表中的结果.使用了from-in-select语句,代码如下: public ...
- 简单的同步Socket程序服务端
首先,Socket是.Net提供的 System.Net.Sockets命名空间的Scoket类为网络通信提供了一套丰富的方法和属性 服务器按照Socket的基本流程 先创建Socket 在用Bind ...
- python 实现一个简单tcp epoll socket
python 实现一个epoll server #!/usr/bin/env python #-*- coding:utf-8 -*- import socket import select impo ...
- import socket模块二
---恢复内容开始--- 优化两个小脚本实现不间断聊天: server.py: import socket sk = socket.socket() # 创建socket addess = ('127 ...
- Socket学习总结系列(二) -- CocoaAsyncSocket
这是系列的第二篇 这是这个系列文章的第二篇,要是没有看第一篇的还是建议看看第一篇,以为这个是接着第一篇梳理的 先大概的总结一下在上篇的文章中说的些内容: 1. 整理了一下做IM我们有那些途径,以及我们 ...
- C# Socket系列三 socket通信的封包和拆包
通过系列二 我们已经实现了socket的简单通信 接下来我们测试一下,在时间应用的场景下,我们会快速且大量的传输数据的情况! class Program { static void Main(stri ...
- socket编程——一个简单的样例
从一个简单的使用TCP样例開始socket编程,其基本过程例如以下: server client ++ ...
- socket计划——一个简单的例子
从一个简单易用TCP样品开始socket计划,的基本过程例如下列: server client +++ ...
随机推荐
- Linux下PHP安装oci8扩展
PHP通常搭配Mysql使用,但有时候也会连接到Oracle数据库.安装PHP的oci8扩张之前,需要先安装Oracle Instant Client( basic 或 basic lite 版就行了 ...
- spring核心框架体系结构
很多人都在用spring开发java项目,但是配置maven依赖的时候并不能明确要配置哪些spring的jar,经常是胡乱添加一堆,编译或运行报错就继续配置jar依赖,导致spring依赖混乱,甚至下 ...
- android权限permission大全
1.Android.permission.WRITE_USER_DICTIONARY允许应用程序向用户词典中写入新词 2.android.permission.WRITE_SYNC_SETTINGS写 ...
- 利用jmSlip写一个移动端顶部日历选择组件
可滚动选日期,并限制哪些日期可选和不可选. 主要用来根据后台返回生成一个日期选择器. 具体实现可关注jmslip: https://github.com/jiamao/jmSlip 示例:http:/ ...
- 将EnyimMemcached从.NET Core RC1升级至RC2
.NET Core RC1时project.json中的配置如下: { "version": "3.2.4", "summary": &qu ...
- JavaScript使用DeviceOne开发实战(一) 配置和起步
2015 年 9 月 底,DeviceOne Release发布.至此,DeviceOne 基本完成了对多端的支持.基于 DeviceOne 可以: HTML5.Android.iOS.Windows ...
- 团队项目——站立会议DAY12
第十二次站立会议记录: 参会人员:张靖颜,钟灵毓秀,何玥,赵莹,王梓萱 项目进展: 1.张靖颜:已经将部分代码完成,对一些模块化的功能进行扩展,对已具备的功能进行完善. 2.钟灵毓秀:对代码进行了修改 ...
- [.net 面向对象编程基础] (22) 事件
[.net 面向对象编程基础] (22) 事件 事件(Event)是学习.net面向对象编程很重要的一部分,在学习事件之前,我们实际上已经在很多地方使用了事件,比如控件的click事件等,这些都是. ...
- Unity3D骨骼动画的分解(CleanData.Ani详解)
CleanData是什么 CleanData以前没有特定的名字,(在easydown这个开源项目中,作为一个GameObjParser模块存在).在某三国项目中,我们使用GameObjParser将N ...
- 线程池ThreadPool知识碎片和使用经验速记
ThreadPool(线程池)大概的工作原理是,初始时线程池中创建了一些线程,当应用程序需要使用线程池中的线程进行工作,线程池将会分配一个线程,之后到来的请求,线程池都会尽量使用池中已有的这个线程进行 ...