


版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C# Socket多线程编程实例时间:2010-09-05 23:42来源:未知作者:admin点击:1073次我要投稿 高质量的ASP.NET 空间,完美支持1.0/2.0/3.5/4.0/MVC等C#是微软随着VS.net新推出的一门语言。它作为一门新兴的语言,有着C+啲强健,又有着VB等的RAD 特性。而且,微软推出C#主要的目的是为了对抗Sun公司的Java。大家都知道Java语言的强大功能, 尤其在网络编程方面。于是,C#在网络编程方面也自然不甘落后于人。本文就向大家介绍一下C虾实现套接字(Sockets)编程的一些基本知识,以期能使大家对此有个大致了解。首先,我向大家介绍一下 套接
2、字的概念。套接字基本概念:套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。可以将套接字看作不同主 机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域 中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的 套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。各种进程使用这 个相同的域互相之间用In ternet协议簇来进行通信。套接字可以根据通信性质分类,这种性质对于用户是可见的。应用程序一般仅在同一类的套接字 间进行通信。不过只要底层的通信协议允许,不同类型的套接字间也照样
3、可以通信。套接字有两种不同 的类型:流套接字和数据报套接字。套接字工作原理:要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户机端,我们称之为ClientSocket,另一个运行于服务器端,我们称之为ServerSocket。根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤: 服务器监听,客户端请求,连接确认。所谓服务器监听,是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态, 实时监控网络状态。所谓客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为 此,客户端的套接字必须首先描述它要连接的服务器的套接
4、字,指出服务器端套接字的地址和端口号, 然后就向服务器端套接字提出连接请求。所谓连接确认,是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应 客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此 描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。C中的套接字编程实例:通过向大家简单的介绍套接字的基本概念和实现套接字编程的基本原理,我想大家对套接字编程 已有了初步的了解。不过,上面介绍的仅仅是基本概念和原理,要真正运用还是需要一定的工作的。对 基本概念和原理的真正理解的最好方法莫过于自己动手做一个
5、实例,下面我就向大家介绍一个很好的用C#实现套接字编程的实例一一聊天室程序。本程序是基于C/S (服务器/客户端)构架的,程序包含一个服务器端的应用程序和一个客户端的 应用程序。首先,在服务器上运行服务器端的应用程序,该程序一运行就开始服务器监听。然后,在客 户机上就可以打开客户端的应用程序。程序打开后可以与服务器端应用程序进行连接,即进行客户端请 求。在连接确认后,客户端用户可以和其他的客户端用户进行聊天。客户端人数没有限制,同时还支持“悄悄话”聊天模式,支持聊天记录。所以这是一个学习套接字编程的相当不错的例子。而且,程序中 为了处理每个客户端的信息还用到了多线程机制。在每个客户端与服务器端
6、连接成功后,它们之间就建 立一个线程。这样运用了多线程之后,客户端之间就不会相互影响,即使其中一个出了错误也不会影响 到另一个。下面,我就向大家具体介绍该实例:服务器端程序:1 .打开VS.net,新建一个C#的模板为“W indows应用程序”的项目,不妨命名为“ ChatServer ”。2 .布置界面。只需在界面上添加一个 ListBox控件即可,该控件主要用于显示客户端的用户的 一些信息的。图象如下:3 .服务器端程序的代码编写。对于服务器端,主要的作用是监听客户端的连接请求并确认其请求。程序一开始便打开一个 StartListe ning ()线程。private void Star
7、tListe nin g()liste ner = new TcpListe ner(liste nport);liste ner.Start();while (true)trySocket s = liste ner.AcceptSocket();clie ntsocket = s;clie ntservice = new Thread( new ThreadStart(ServiceClie nt);clie ntservice.Start();catch(Excepti on e)Console.WriteLine(e.ToString() ); 该线程是一直处于运行状态的。当服务器端接
8、收到一个来自客户端的连接请求后,它就打开一个ServiceClient ()线程来服务客户端。当一个连接被建立后,每个客户端就被赋予一个属于它自己的 套接字。同时,一个 Client 类的对象被建立。该对象包含了客户端的一些相关信息,该信息被保存在 一个数组列表中。 Client 类如下:using System;using System.Threading;namespace ChatServerusing System.Net.Sockets;using System.Net;/ Client 的摘要说明。/public class Clientprivate Thread clthrea
9、d;private EndPoint endpoint;private string name;private Socket sock;public Client(string _name, EndPoint _endpoint, Thread _thread, Socket _sock)/ TODO: 在此处添加构造函数逻辑clthread = _thread;endpoint = _endpoint;name = _name;sock = _sock;public override string ToString()return endpoint.ToString()+ " :
10、" + name;public Thread CLThreadgetreturn clthread;setclthread = value;public EndPoint Hostgetreturn endpoint;setendpoint = value; public string Namegetreturn name; setname = value; public Socket Sock getreturn sock; setsock = value; 程序的主体部分应是 ServiceClient ()函数。该函数是一个独立的线程, 其主要部分是一个 while 循环。在循
11、环体内,程序处理各种客户端命令。服务器端接收来自客户端的以 ASCII 码给出的字符串, 其中包含了一个形式的分隔符。字符串中“ 以前的部分就是具体的命令,包括CONNCHATPRIV、 GON四种类型。CON命令建立一个新的客户端连接,将现有的用户列表发送给新用户并告知其他用户 有一个新用户加入。CHAT命令将新的信息发送给所有用户。PRIV命令将悄悄话发送给某个用户。GONE 命令从用户列表中除去一个已离开的用户并告知其他的用户某某已经离开了。同时,GON命令可以设置布尔型的变量 keepalive 为 false 从而结束与客户端连接的线程。 ServiceClient ()函数如下:p
12、rivate void ServiceClient()Socket client = clientsocket; bool keepalive = true;while (keepalive)Byte buffer = new Byte1024;client.Receive(buffer);string clientcommand = System.Text.Encoding.ASCII.GetString(buffer);string tokens = clientcommand.Split(new Char'|');Console.WriteLine(clientcomma
13、nd);if (tokens0 = "CONN") for(int n=0; nClient cl = (Client)clientsn; SendToClient(cl, "JOIN|" + tokens1); EndPoint ep = client.RemoteEndPoint;Client c = new Client(tokens1, ep, clientservice, client); clients.Add(c);string message = "LIST|" + GetChatterList() +"rn
14、" SendToClient(c, message);lbClients.Items.Add(c);if (tokens0 = "CHAT")for(int n=0; nClient cl = (Client)clientsn;SendToClient(cl, clientcommand);if (tokens0 = "PRIV")string destclient = tokens3;for(int n=0; nClient cl = (Client)clientsn; if(cl.Name.CompareTo(tokens3) = 0) S
15、endToClient(cl, clientcommand); if(cl.Name.CompareTo(tokens1) = 0) SendToClient(cl, clientcommand);if (tokens0 = "GONE")int remove = 0;bool found = false;int c = clients.Count;for(int n=0; nClient cl = (Client)clientsn;SendToClient(cl, clientcommand); if(cl.Name.CompareTo(tokens1) = 0) rem
16、ove = n;found = true; lbClients.Items.Remove(cl);if(found) clients.RemoveAt(remove); client.Close();keepalive = false;Form1.cs文件)程序运这样,服务器端程序就基本完成了。(其他略次要的代码可以参见源代码中的 行图示如下:客户端程序:1 .打开VS.net,新建一个C#的模板为“ Win dows应用程序”的项目,不妨命名为 ChatClient ”。2 .布置界面。往界面上添加一个 ListBox控件(用于显示用户列表),一个 RichTextBox控件 (用于显示聊天
17、消息以及系统消息),一个 TextBox控件(用于发送消息),一个 CheckBox控件(确 定是否为悄悄话),一个StatusBar控件以及四个Button控件(分别为“连接”、“断开连接”、“开 始记录”、“发送”)。各个控件的属性设置可以参见源代码中的具体设置,这里从略。界面设计好后 的图象如下:12T D.Q. 1 IQ5S fitt 127.0.0. 1 :10&9127.0.0 1 :10BC : JraiLki iir» :一iraiJCI2S1 ip 111 | J111ll|IUIIIIBI II . 0 1 1061 Emilv上转于【新容网 m. 1CK
18、IR. COfflJ3 客户端程序的代码编写当客户端试图和服务器端进行连接时,一个连接必须建立而且得向服务器端进行注册。EstablishConnection ( )函数运用一个 TcpClient 来和服务器端取得连接, 同时创建一个 NetworkStream 来发送消息。还有,端口号和服务器端的是保持一致的,均为5555。EstablishConnection()函数如下:private void EstablishConnection()statusBar1.Text = " 正在连接到服务器 " tryclientsocket = new TcpClient(se
19、rveraddress,serverport);ns = clientsocket.GetStream();sr = new StreamReader(ns);connected = true;catch (Exception)MessageBox.Show("不能连接到服务器!","错误",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);statusBar1.Text = " 已断开连接 "在和服务器端连接成功后,程序就用RegisterWithServer ()函数向服务器端发送
20、一个 CON命令。 该命令先是发送该用户的名称,然后从服务器端获得其他所有用户的列表,所有用户列表是在 ListBox 控件中显示的。该函数如下:private void RegisterWithServer()trystring command = "CONN|" + ChatOut.Text;Byte outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray(); ns.Write(outbytes,0,outbytes.Length);string serverresponse = sr.Re
21、adLine(); serverresponse.Trim();string tokens = serverresponse.Split(new Char'|');if(tokens0 = "LIST")statusBar1.Text = " 已连接"btnDisconnect.Enabled = true;for(int n=1; nlbChatters.Items.Add(tokensn.Trim(new char'r','n'); this.Text = clientname + " :已连
22、接到服务器 "catch (Exception)MessageBox.Show('注册时发生错误!","错误",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);在此之后,当然就是用户之间的聊天了,由 ReceiveChat ()函数来完成。该函数是一个独立的线程, 它处理所有用户获得的消息和用户发送的消息。它主要处理了 CHAT PRIV JOIN、GONEQU99V等命令, 处理的方法和服务器端的类似。具体函数实现如下:private void ReceiveChat()bool keepal
23、ive = true;while (keepalive)tryByte buffer = new Byte2048;ns.Read(buffer,0,buffer.Length);string chatter = System.Text.Encoding.ASCII.GetString(buffer);string tokens = chatter.Split(new Char'|');if (tokens0 = "CHAT") rtbChatIn.AppendText(tokens1);if(logging) logwriter.WriteLine(tok
24、ens1);if (tokens0 = "PRIV")rtbChatIn.AppendText("Private from ");rtbChatIn.AppendText(tokens1.Trim() ); rtbChatIn.AppendText(tokens2 + "rn");if(logging)logwriter.Write("Private from ");logwriter.Write(tokens1.Trim() ); logwriter.WriteLine(tokens2 + "rn&qu
25、ot;);if (tokens0 = "JOIN")rtbChatIn.AppendText(tokens1.Trim() );rtbChatIn.AppendText(" has joined the Chatrn");if(logging) logwriter.WriteLine(tokens1+" has joined the Chat");string newguy = tokens1.Trim(new char'r','n'); lbChatters.Items.Add(newguy);if
26、(tokens0 = "GONE") rtbChatIn.AppendText(tokens1.Trim() ); rtbChatIn.AppendText(" has left the Chatrn"); if(logging) logwriter.WriteLine(tokens1+" has left the Chat"); lbChatters.Items.Remove(tokens1.Trim(new char'r','n');if (tokens0 = "QU99v")
27、ns.Close(); clientsocket.Close(); keepalive = false; statusBar1.Text = " 服务器端已停止 " connected= false;btnSend.Enabled = false; btnDisconnect.Enabled = false;catch(Exception) 通过以上的一些函数,客户端程序之间就可以进行自由地聊天了,各个用户之间还可以互相发送 悄悄话。所以程序已经实现了聊天室的基本功能了,不过最后各个用户还要正常地退出,那就要用到 QuitChat ()函数了。该函数的具体实现如下:priv
28、ate void QuitChat() if(connected)trystring command = "GONE|" + clientname;Byte outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray(); ns.Write(outbytes,0,outbytes.Length);clientsocket.Close();catch(Exception) if(logging) logwriter.Close(); if(receive != null && recei
29、ve.IsAlive) receive.Abort();this.Text ="客户端";到此为止,客户端程序的主要部分都已经介绍完毕。还有一些按钮控件的消息处理函数可以参见 源代码。同时,程序中还有一个聊天记录功能,该功能和现在流行的聊天软件的记录功能类似。不过限 于篇幅,在这里就不一一介绍了,有兴趣的读者可以研究一下本文后面的源代码。这样,客户端程序就完成了。程序运行图示如下:总结:本文向大家初步介绍了套接字的基本概念和实现套接字编程的基本原理,还通过一个很好的实例向大家展示了在C虾进行套接字编程的实现方法和一些编程技巧。从中,我们不难发现运用C#进行套接字编程乃至网络
30、编程有许多优越之处。实例程序实现的思路清晰明了而且通俗易懂,是一个相当不错 的例子,希望各位能好好研读。同时还希望大家能进一步完善该程序,使之功能更强大、界面更友好。 在此之后,当然就是用户之间的聊天了,由ReceiveChat ()函数来完成。该函数是一个独立的线程,它处理所有用户获得的消息和用户发送的消息。它主要处理了 CHAT PRIV JOIN、GONEQU99V等命令, 处理的方法和服务器端的类似。具体函数实现如下:private void ReceiveChat()bool keepalive = true;while (keepalive)tryByte buffer = new
31、 Byte2048;n s.Read(buffer,0,buffer.Le ngth);stri ng chatter = System.Text.E ncodi ng.ASCII.GetStri ng(buffer);string tokens = chatter.Split(new Char'|');if (tokens0 = "CHAT") rtbChatIn.AppendText(tokens1);if(logging) logwriter.WriteLine(tokens1);if (tokens0 = "PRIV") rtbC
32、hatIn.AppendText("Private from "); rtbChatIn.AppendText(tokens1.Trim() ); rtbChatIn.AppendText(tokens2 + "rn");if(logging) logwriter.Write("Private from "); logwriter.Write(tokens1.Trim() ); logwriter.WriteLine(tokens2 + "rn");if (tokens0 = "JOIN") r
33、tbChatIn.AppendText(tokens1.Trim() ); rtbChatIn.AppendText(" has joined the Chatrn"); if(logging) logwriter.WriteLine(tokens1+" has joined the Chat");string newguy = tokens1.Trim(new char'r','n'); lbChatters.Items.Add(newguy);if (tokens0 = "GONE") rtbCha
34、tIn.AppendText(tokens1.Trim() ); rtbChatIn.AppendText(" has left the Chatrn"); if(logging) logwriter.WriteLine(tokens1+" has left the Chat");lbChatters.Items.Remove(tokens1.Trim(new char'r','n'); if (tokens0 = "QU99v") ns.Close(); clientsocket.Close(); keepalive = false;statusBar1.Text = " 服务器端已停止 "
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025采购合同示范文本
- 合同范本模板哪里有
- 水塔上拆迁合同范本
- 2025新房购房合同范本新房买卖合同的合同范本
- 家电转卖维修合同范本
- 贵州茶叶合同范本
- 荒地补偿协议合同范本
- 瓦房扩建改造合同范本
- 出口长期供货合同范本
- 纸箱模具采购合同范本
- 慎交友-不交损友课件
- 2025年海军专业技能类文职人员招聘(卫生员兼司机)历年参考题库含答案详解(5卷)
- 2025年锦州辅警考试题库(附答案)
- 宾馆前台培训课件
- 消防安全专项施工方案及应急预案
- 2025年粮食局考试试题及答案
- 2025年高考生物甘肃卷试题答案解读及备考指导(精校打印)
- WST856-2025安全注射标准解读
- 医美项目规划方案(3篇)
- 2025年全国反诈骗知识竞赛试题含答案
- 电网采购管理办法
评论
0/150
提交评论