接下来是服务器部分,采用异步模式,新建了一个AsynServer类,用于存放socket服务器代码,主要有4个方法:

有一个全局socket,下面四个方法中都用到。

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

类框架如下:

1.构造方法public AsynServer(IPEndPoint endpoint,int listenMaxNum)

  用于初始化socket服务器,IPEndPoint参数是socket绑定的终结点,listenMaxNum参数是监听队列的挂起的最大长度,代码如下:

  public AsynServer(IPEndPoint endpoint,int listenMaxNum)
{
socket.Bind(endpoint); //绑定终结点
socket.Listen(listenMaxNum);//将socket至于侦听状态,设置挂起队列最大值为listenMaxNum
Console.WriteLine("正在连接客户端....");
AsynAccept(); //开始异步监听
// return socket;
}

2.异步监听方法public void AsynAccept()

public void AsynAccept()
{
socket.BeginAccept(asyncResult => {
socket = socket.EndAccept(asyncResult); //异步监听成功,返回socket
Console.WriteLine("客户端{0}异步连接成功", socket.RemoteEndPoint.ToString());
AsynReceive();
AsynSend("Server:Hello,client!");
}, null);
}

需注意的是异步socket的BeginAccept()方法必须以EndAccept()方法结束,EndAccept(asyncResult)通过回调BeginAccept中的asyncResult状态信息返回socket,这个socket是与客户端建立连接后的socket,需要把它赋给全局socket(后面的方法中会调用)。

另外,AsynAccept并不会阻塞主线程,因为系统会为BeginAccept()方法自动开一个线程,并阻塞该线程直到收到客户端连接,回调lamda表达式中的接收代码。

采用lamda变得式写的回调函数,不熟悉的同学请恶补一下吧,用起来很方便的:-)

连接成功了会收到客户端发来的信息,(AsynReceive()也是异步的,不会阻碍主线程),并给客户端发送问候信息,(AsynReceive()和AsynSend()都是异步的,不会阻碍主线程)。

3.异步接收方法private  void AsynReceive()

  private  void AsynReceive()
{
byte[] data = new byte[];//接收缓存
string receiveStr;
socket.BeginReceive(data, , data.Length, SocketFlags.None, asyncResult => {
int length = socket.EndReceive(asyncResult);
if (length != )
{
receiveStr = Encoding.ASCII.GetString(data, , length);//获取缓存中的信息
Console.WriteLine(receiveStr); AsynReceive();//继续开新线程接收
}
else { Console.WriteLine("客户端{0}:关闭socket连接", socket.RemoteEndPoint.ToString());//socket.RemoteEndPoint.ToString()是客户端IP地址
socket.Close();
}
}, null); }

AsynReceive()

4.异步发送方法public void AsynSend()

 public void AsynSend(string msg)
{
byte[] data = Encoding.UTF8.GetBytes(msg);
socket.BeginSend(data, , data.Length, SocketFlags.None, asyncResult =>
{
int length = socket.EndSend(asyncResult);
Console.WriteLine("message send to {0} successfully", socket.RemoteEndPoint.ToString());
}, null);
}

public void AsynSend(string msg)

因为socket收发都是采用字节流的形式,所以接收需要用byte[] data = new byte[1024],缓存收到的字节流,然后通过Encoding.ASCII.GetString(data, 0, length)方法把字节流转化为字符串输出;发送通过byte[] data = Encoding.UTF8.GetBytes(msg),把字符串信息转化为字节流发送。EndReceive(),EndSend()方法返回的都是收发字节数(int)

以上都是最简单的,只能实现基本的通信功能,后期会在此基础上完善,帮助初学者少走弯路,我当时可是学的头昏眼花-_-||

下篇是采用与服务器完全不同模式的客户端,同步模式

Socket异步通信学习二的更多相关文章

  1. Socket异步通信学习一

    最近在做一个频谱管理项目,负责通信模块,自己也是小白,重头学起,直至今天通信基本框架已经完成,把自己在学习中的心得与大家分享一下,做一个socket系列的博文,顺便加固一下自己对socket通信的认识 ...

  2. Socket异步通信学习三

    接下来是客户端部分,采用同步接收模式,在SocketClient项目中新建了一个SynServer类,用于存放socket服务器代码,和AsynServer类似,主要有4个方法: 有一个全局socke ...

  3. Linux学习之socket编程(二)

    Linux学习之socket编程(二) 1.C/S模型——UDP UDP处理模型 由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实 ...

  4. TCP协议和socket API 学习笔记

    本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类:  原文地址:TCP协议和socket API 学习笔记 作者:gilb ...

  5. C#高性能大容量SOCKET并发(二):SocketAsyncEventArgs封装

    原文:C#高性能大容量SOCKET并发(二):SocketAsyncEventArgs封装 1.SocketAsyncEventArgs介绍 SocketAsyncEventArgs是微软提供的高性能 ...

  6. emberjs学习二(ember-data和localstorage_adapter)

    emberjs学习二(ember-data和localstorage_adapter) 准备工作 首先我们加入ember-data和ember-localstorage-adapter两个依赖项,使用 ...

  7. ReactJS入门学习二

    ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...

  8. socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto

    socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...

  9. TweenMax动画库学习(二)

    目录            TweenMax动画库学习(一)            TweenMax动画库学习(二)            TweenMax动画库学习(三)            Tw ...

随机推荐

  1. iOS开发之UILabel

    UILabel是iOS开发中常用的一个组件,主要用来显示内容. UILabel的主要使用如下: /*尺寸*/ CGRect labelRect = CGRectMake(100, 100, 80, 4 ...

  2. java.lang.ExceptionInInitializerError的原因(转)

    这个错误是说变量初始化出现问题,通常出现在静态变量尤其是单例模式.这种问题往往是初始化顺序不对造成的,下面举个简单的例子. import java.util.HashMap; import java. ...

  3. Go 学习笔记(一)

    随着Go的应用越来越火热,自己也终于开始学习了.平时经常用C,看着Go还是比较亲切的.好了,开始. 今天主要是按照书上的内容自己简单的实践了下最基本的输出,以及网页功能,上代码: package ma ...

  4. 网页加载速度优化2--先加载css,然后再加载js文件。

    网页加载时,是按从上到下,从左到右的顺序加载的.所以一定要先加载css文件(不要让用户看到一个杂乱无章的页面),最后再加载js文件,js一般都是处理功能的,所以不需要提前加载.先给用户观感,再给用户上 ...

  5. [原][Android]All WebView methods must be called on the same thread.

    问题 webView调用JS出错. class TestJS {         ......         public TestJS(){         }                   ...

  6. 派遣例程与IRP结构

    提到派遣例程,必须理解IRP(I/O Request Package),即"输入/输出请求包"这个重要数据结构的概念.Ring3通过DeviceIoControl等函数向驱动发出I ...

  7. HDU 1024 DP Max Sum Plus Plus

    题意:本题的大致意思为给定一个数组,求其分成m个不相交子段和最大值的问题. kuangbin专题. dp[i][j]=Max(dp[i][j-1]+a[j] , max( dp[i-1][k] ) + ...

  8. java继承和多态

    父类和子类 如果类C1扩展自另一个类C2,那么C1称为子类或派生类,C2称为父类或基类.派生类可以从它的基类中继承可访问的数据域和方法,还可添加新数据域和新方法 例如:实现一个几何图形基类; clas ...

  9. 【数论】Baby Step Giant Step

    被数论怒虐了一天 心力憔悴啊 感觉脑细胞已经快消耗殆尽了>_< 但是今天还是会了很多之前觉得特别神的东西 比如BSGS 之前听了两遍 好像都因为听得睡着了没听懂-.- 今天终于硬着头皮学会 ...

  10. POJ1185 - 炮兵阵地(状态压缩DP)

    题目大意 中文的..直接搬过来... 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平 ...