你得学会并且学得会的Socket编程基础知识.docx_第1页
你得学会并且学得会的Socket编程基础知识.docx_第2页
你得学会并且学得会的Socket编程基础知识.docx_第3页
你得学会并且学得会的Socket编程基础知识.docx_第4页
你得学会并且学得会的Socket编程基础知识.docx_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

这一篇文章,我将图文并茂地介绍Socket编程的基础知识,我相信,如果你按照步骤做完实验,一定可以对Socket编程有更好地理解。第一步:创建解决方案第二步:创建服务端程序这里可以选择“Console Application”这个类型,比较方便调试然后编写如下代码,实现服务器的基本功能using System;using System.Collections.Generic;using System.Linq;using System.Text;/额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /将该socket绑定到主机上面的某个端口 /方法参考:/zh-cn/library/.sockets.socket.bind.aspx socket.Bind(new IPEndPoint(IPAddress.Any, 4530); /启动监听,并且设置一个最大的队列长度 /方法参考:/zh-cn/library/.sockets.socket.listen(v=VS.100).aspx socket.Listen(4); Console.WriteLine(Server is ready!); Console.Read(); 现在可以启动调试一下看看效果如何,正常情况下应该会看到一个提示,因为我们需要在TCP 4530端口进行监听,所以防火墙会有提示。点击“Allow access”这样,我们的服务器就可以开始监听了。但是这有什么用呢?是的,没有什么用。我们还需要为服务器添加一些功能,例如接受传入的请求,给客户端发送消息,或者从客户端接收消息等等第三步:接受传入的请求我们需要通过Accept,或者(BeginAccept)来接受传入的请求,请注意下面代码中的红色部分using System;using System.Collections.Generic;using System.Linq;using System.Text;/额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /将该socket绑定到主机上面的某个端口 /方法参考:/zh-cn/library/.sockets.socket.bind.aspx socket.Bind(new IPEndPoint(IPAddress.Any, 4530); /启动监听,并且设置一个最大的队列长度 /方法参考:/zh-cn/library/.sockets.socket.listen(v=VS.100).aspx socket.Listen(4); /开始接受客户端连接请求 /方法参考:/zh-cn/library/.sockets.socket.beginaccept.aspx socket.BeginAccept(new AsyncCallback(ar) = /这就是客户端的Socket实例,我们后续可以将其保存起来 var client = socket.EndAccept(ar); /给客户端发送一个欢迎消息 client.Send(Encoding.Unicode.GetBytes(Hi there, I accept you request at +DateTime.Now.ToString(); ), null); Console.WriteLine(Server is ready!); Console.Read(); wow,看起来不错对吧,我们赶紧做一个客户端来测试一下吧第四步:创建客户端我们还是使用一个Console Application添加如下的代码,并且创建客户端连接using System;using System.Collections.Generic;using System.Linq;using System.Text;/导入的命名空间using System.Net.Sockets;namespace SocketClient class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /连接到指定服务器的指定端口 /方法参考:/zh-cn/library/.sockets.socket.connect.aspx socket.Connect(localhost, 4530); Console.WriteLine(connect to the server); Console.Read(); 依次选择SocketServer和SocketClient这两个项目,分别将其启动为调试状态(右键菜单,Debug=Start new instance)我们看到两个程序都工作正常。但是,在客户端怎么没有收到服务器发过来的消息呢?那是因为,我们没有在客户端提供这方面的功能。第五步:在客户端中实现接受消息的方法using System;using System.Collections.Generic;using System.Linq;using System.Text;/导入的命名空间using System.Net.Sockets;namespace SocketClient class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /连接到指定服务器的指定端口 /方法参考:/zh-cn/library/.sockets.socket.connect.aspx socket.Connect(localhost, 4530); /实现接受消息的方法 var buffer = new byte1024;/设置一个缓冲区,用来保存数据 /方法参考:/zh-cn/library/.sockets.socket.beginreceive.aspx socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ar) = /方法参考:/zh-cn/library/.sockets.socket.endreceive.aspx var length = socket.EndReceive(ar); /读取出来消息内容 var message = Encoding.Unicode.GetString(buffer, 0, length); /显示消息 Console.WriteLine(message); ), null); Console.WriteLine(connect to the server); Console.Read(); 请注意以上红色的部分,我们用了BeginReceive方法进行异步的消息侦听,如果收到了,我们就打印出来看起来已经实现了我们需求了:服务器给客户端发了一个消息,而客户端也已经收到了。但是,这远远不够,因为它们之间的通讯不仅仅是一次性的,那么如果服务器要不断地给客户端发消息,例如每隔两秒钟就发送一个消息,如何实现呢?第六步:实现服务器定期向客户端发消息using System;using System.Collections.Generic;using System.Linq;using System.Text;/额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /将该socket绑定到主机上面的某个端口 /方法参考:/zh-cn/library/.sockets.socket.bind.aspx socket.Bind(new IPEndPoint(IPAddress.Any, 4530); /启动监听,并且设置一个最大的队列长度 /方法参考:/zh-cn/library/.sockets.socket.listen(v=VS.100).aspx socket.Listen(4); /开始接受客户端连接请求 /方法参考:/zh-cn/library/.sockets.socket.beginaccept.aspx socket.BeginAccept(new AsyncCallback(ar) = /这就是客户端的Socket实例,我们后续可以将其保存起来 var client = socket.EndAccept(ar); /给客户端发送一个欢迎消息 client.Send(Encoding.Unicode.GetBytes(Hi there, I accept you request at +DateTime.Now.ToString(); /实现每隔两秒钟给服务器发一个消息 /这里我们使用了一个定时器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) = client.Send(Encoding.Unicode.GetBytes(Message from server at +DateTime.Now.ToString(); ; timer.Start(); ), null); Console.WriteLine(Server is ready!); Console.Read(); 我们还要实现在客户端一直监听消息的机制,而不是一次性接收.请注意下面红色的部分using System;using System.Collections.Generic;using System.Linq;using System.Text;/导入的命名空间using System.Net.Sockets;namespace SocketClient class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /连接到指定服务器的指定端口 /方法参考:/zh-cn/library/.sockets.socket.connect.aspx socket.Connect(localhost, 4530); Console.WriteLine(connect to the server); /实现接受消息的方法 /方法参考:/zh-cn/library/.sockets.socket.beginreceive.aspx socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage),socket); Console.Read(); static byte buffer = new byte1024; public static void ReceiveMessage(IAsyncResult ar) try var socket = ar.AsyncState as Socket; /方法参考:/zh-cn/library/.sockets.socket.endreceive.aspx var length = socket.EndReceive(ar); /读取出来消息内容 var message = Encoding.Unicode.GetString(buffer, 0, length); /显示消息 Console.WriteLine(message); /接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了) socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); catch(Exception ex) Console.WriteLine(ex.Message); 重新调试起来,看起来的效果如下图所示我们继续做下面的实验,一步一步地研究Socket通讯中可能遇到的一些问题请先关闭掉客户端这个程序,而不要关闭服务端程序,这时会发现一个错误这个错误很容易理解,因为客户端已经关闭,也就是客户端那个Socket已经不存在了,服务器还继续向它发送消息当然会出错。所以,从可靠性方面的考虑,我们必须在发送消息之前检测Socket的活动状态第七步:检测客户端的活动状态using System;using System.Collections.Generic;using System.Linq;using System.Text;/额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /将该socket绑定到主机上面的某个端口 /方法参考:/zh-cn/library/.sockets.socket.bind.aspx socket.Bind(new IPEndPoint(IPAddress.Any, 4530); /启动监听,并且设置一个最大的队列长度 /方法参考:/zh-cn/library/.sockets.socket.listen(v=VS.100).aspx socket.Listen(4); /开始接受客户端连接请求 /方法参考:/zh-cn/library/.sockets.socket.beginaccept.aspx socket.BeginAccept(new AsyncCallback(ar) = /这就是客户端的Socket实例,我们后续可以将其保存起来 var client = socket.EndAccept(ar); /给客户端发送一个欢迎消息 client.Send(Encoding.Unicode.GetBytes(Hi there, I accept you request at +DateTime.Now.ToString(); /实现每隔两秒钟给服务器发一个消息 /这里我们使用了一个定时器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) = /检测客户端Socket的状态 if(client.Connected) try client.Send(Encoding.Unicode.GetBytes(Message from server at + DateTime.Now.ToString(); catch(SocketException ex) Console.WriteLine(ex.Message); else timer.Stop(); timer.Enabled = false; Console.WriteLine(Client is disconnected, the timer is stop.); ; timer.Start(); ), null); Console.WriteLine(Server is ready!); Console.Read(); 上面代码的逻辑很清楚,但有时候还是会触发那个SocketException。为什么呢?这是因为我们的Timer是每隔两秒钟检查一次,那么就很可能有一种情况,我们检查的时候,它还是连接状态,消息发出去之后,它断开了。这种情况肯定是存在的。所以要用Try.catch的结构目前我们实现的场景很简单,服务器只管发消息,客户端只管收消息。但实际工作中,可能希望服务器和客户端都能收发消息。请看下一节第八步:实现双向收发消息先看服务端的修改using System;using System.Collections.Generic;using System.Linq;using System.Text;/额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /将该socket绑定到主机上面的某个端口 /方法参考:/zh-cn/library/.sockets.socket.bind.aspx socket.Bind(new IPEndPoint(IPAddress.Any, 4530); /启动监听,并且设置一个最大的队列长度 /方法参考:/zh-cn/library/.sockets.socket.listen(v=VS.100).aspx socket.Listen(4); /开始接受客户端连接请求 /方法参考:/zh-cn/library/.sockets.socket.beginaccept.aspx socket.BeginAccept(new AsyncCallback(ar) = /这就是客户端的Socket实例,我们后续可以将其保存起来 var client = socket.EndAccept(ar); /给客户端发送一个欢迎消息 client.Send(Encoding.Unicode.GetBytes(Hi there, I accept you request at +DateTime.Now.ToString(); /实现每隔两秒钟给服务器发一个消息 /这里我们使用了一个定时器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) = /检测客户端Socket的状态 if(client.Connected) try client.Send(Encoding.Unicode.GetBytes(Message from server at + DateTime.Now.ToString(); catch(SocketException ex) Console.WriteLine(ex.Message); else timer.Stop(); timer.Enabled = false; Console.WriteLine(Client is disconnected, the timer is stop.); ; timer.Start(); /接收客户端的消息(这个和在客户端实现的方式是一样的) client.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,new AsyncCallback(ReceiveMessage),client); ), null); Console.WriteLine(Server is ready!); Console.Read(); static byte buffer = new byte1024; public static void ReceiveMessage(IAsyncResult ar) try var socket = ar.AsyncState as Socket; /方法参考:/zh-cn/library/.sockets.socket.endreceive.aspx var length = socket.EndReceive(ar); /读取出来消息内容 var message = Encoding.Unicode.GetString(buffer, 0, length); /显示消息 Console.WriteLine(message); /接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了) socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); catch(Exception ex) Console.WriteLine(ex.Message); 可以看出来,为了让服务器可以接受消息,其实并不需要什么特别的设计,与客户端接受消息其实可以是一样的 再来看看客户端的修改using System;using System.Collections.Generic;using System.Linq;using System.Text;/导入的命名空间using System.Net.Sockets;namespace SocketClient class Program / / Socket Server 演示 / 作者:陈希章 / / static void Main(string args) /创建一个Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); /连接到指定服务器的指定端口 /方法参考:/zh-cn/library/.sockets.socket.connect.aspx socket.Connect(localhost, 4530); Console.WriteLine(connect to the server); /实现接受消息的方法 /方法参考:/zh-cn/library/.sockets.socket.beginreceive.aspx socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); /接受用户输入,将消息发送给服务器端 while(true) var message = Message from client : + Console.ReadLine(); var outputBuffer = Encoding.Unicode.GetBytes(message); socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null); static byte buffer = new byte1024; public static void ReceiveMessage(IAsyncResult ar) try var socket = ar.AsyncState as Socket; /方法参考:/zh-cn/library/.sockets.socket.endreceive.aspx var length = socket.EndReceive(ar); /读取出来消息内容 var message = Encoding

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论