基于Socket服务器端实现本例主要是创建多客户端与服务器之间的数据传输,首先设计服务器。打开VS2008,在D:\C#\ch17目录下创建名为SocketServer的Windows应用程序。打开工程,往当前窗体中添加控件,如表17-6所示。 表17-6 添加控件列表数据库
控 件服务器 |
Name网络 |
Textide |
ListBox函数 |
lbInfo测试 |
|
Labelthis |
labelspa |
|
Button线程 |
button1 |
启动服务器 |
设计好的界面如图17-2所示。 接下来开始运用前面的知识设计服务器,主要分为如下步骤。 (1)首先是对一些命名空间的包含,包括System.Net、System.Net.Sockets、System.IO和System.Threading。而后定义一系列的全局变量,以下所示。
private Socket s; //定义Socket对象 private Thread th; //客户端链接服务器的线程 public Socket cSocket; //单个客户端链接的Socket对象 public NetworkStream ns; //网络流 public StreamReader sr; //流读取 public StreamWriter sw; //流写入 private delegate void SetTextCallback(); //用于操做主线程控件
(2)接下来是设计客户端链接的管理,主要包括服务器与客户端之间的链接和收发数据问题,把它们放在一个函数Communication里,以下所示。
public void Communication() { while (true) { try { cSocket = s.Accept(); //用cSocket来表明该客户端链接 if (cSocket.Connected) //测试是否链接成功 { ns = new NetworkStream(cSocket); //创建网络流,便于数据的读取 sr = new StreamReader(ns); //实例化流读取对象 sw = new StreamWriter(ns); //实例化写入流对象 test(); //从流中读取 sw.WriteLine("收到请求,容许链接"); //向流中写入数据 sw.Flush(); //清理缓冲区 } else { MessageBox.Show("链接失败"); } } catch (SocketException ex) { MessageBox.Show(ex.Message); //捕获Socket异常 } catch (Exception es) { MessageBox.Show("其余异常" + es.Message); //捕获其余异常 } } } //如下代码的用法在第16章有关线程的用法时曾提到过,主要用于从当前线程操做主线程中的控件,这里就不在赘//述 public void send() { lbInfo.Items.Add(sr.ReadLine()+"\n"); } public void test() { SetTextCallback stcb = new SetTextCallback(send); Invoke(stcb); }
(3)定义好与客户端的链接后,接下来须要利用线程来启动,双击“启动服务器”按钮,添加以下代码。
button1.Enabled = false; s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立Socket对象 IPAddress serverIP = IPAddress.Parse("222.18.142.171"); IPEndPoint server = new IPEndPoint(serverIP,13); //实例化服务器的IP和端口 s.Bind(server); s.Listen(10); try { th = new Thread(new ThreadStart(Communication)); //建立线程 th.Start(); //启动线程 label1.Text = "服务器启动成功!"; } catch(Exception ex) { MessageBox.Show("服务器启动失败!" + ex.Message); }
(4)最后在关闭服务器窗口的时候,还应该关闭线程和当前Socket链接,代码以下所示。
protected override void Dispose(bool disposing) { try { if (disposing && (components != null)) { components.Dispose(); th.Abort(); //禁用当前Socket链接中的数据收发 s.Shutdown(System.Net.Sockets.SocketShutdown.Both); s.Close(); } base.Dispose(disposing); } catch { return; } } //接着为当前窗体的FormClosed事件添加以下代码。 this.Close();
至此,服务器就设计完了,下面接着看客户端。 基于Socket客户端实现打开VS2008,在D:\C#\ch17目录下创建名为SocketClient的Windows应用程序。打开工程,往当前窗体中添加控件,如表17-7所示。 表17-7 添加控件列表
控 件 名 |
Name |
Text |
GroupBox |
groupBox1 |
向服务器发送消息 |
Label |
label1 |
发送消息: |
TextBox |
textBox1 |
|
Button |
button2 |
发送 |
ListBox |
lbInfo |
|
GroupBox |
groupBox1 |
服务器回馈信息 |
客户端的设计主要分为如下步骤。 (1)首先要作的工做仍是要引用一些命名空间,以下所示。
using System.IO; using System.Net.Sockets; using System.Net;
而后定义一系列的全局变量,以下所示。
private Socket s; //定义Socket对象 public NetworkStream ns; //网络流 public StreamReader sr; //流读取 public StreamWriter sw; //流写入
(2)双击“发送”按钮,添加以下代码。
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverIP = IPAddress.Parse("222.18.142.171"); //服务器IP try { s.Connect(serverIP, 13); //链接服务器,端口号用13 } catch (Exception ex) { MessageBox.Show(ex.Message); } try { ns = new NetworkStream(s); //实例化网络流 sr = new StreamReader(ns); //实例化流读取对象 sw = new StreamWriter(ns); //实例化写入流对象 sw.WriteLine(textBox1.Text); //将textBox1.Text的数据写入流 sw.Flush(); //清理缓冲区 lbInfo.Items.Add(sr.ReadLine()); //将从流中读取的数据写入lbInfo28 } catch (Exception ex) { MessageBox.Show(ex.Message); //捕获异常 }
(3)最后,关闭Socket链接,释放资源,能够直接在窗体的FormClosed事件中进行,以下所示。s.Shutdown(SocketShutdown.Both);s.Close();至此,服务器和客户端已经所有设计完毕,下面看运行效果。基于Socket的C/S实例的运行首先,启动服务器程序,单击“启动服务器”按钮,如图17-4所示。接着再启动客户端,并在textBox1输入数据(中英文皆可),屡次单击“发送”按钮,如图17-5所示。此时,服务器的状态如图17-6所示。收到客户端发送的数据从图17-6中能够看出,此时服务器已经收到来自客户端的数据,而图17-5中显示客户端也收到了来自服务器的回馈消息。此外,本例还能实现多个客户端向一个服务器同时收发数据,并已经在三台计算机(一个服务器和两个客户端)上测试经过。本例只是实现了服务器与客户端最简单的数据传输,读者若是有兴趣能够在此基础上再添加其余功能,好比能够利用前面讲的数据库知识,在服务器端写个用户登陆验证,让客户端经过验证后才能收发数据等。在网络中,收发数据会常常使用Socket。本节中主要运用了几节中介绍的Socket基础知识完成了一个简单的基于流的C/S模式例子。在下一节中,将介绍另外一种传输方式——基于数据报(UDP)。 |