一步一步教你使用.net进行Socket通信

原文:点击打开链接

一步一步教你使用.net进行Socket通信

本文源代码下载

随着Web技术的发展,Socket通信逐渐被人们遗忘。然而最近Socket应用却又越来越多。尤其是中国移动,中国联通的短信网关就是基于Socket通迅,另外随着大家对MSN、QQ等IM工具通迅协议的研究。协议内容也随处都可以找到。想要制作自己的MSN、QQ客户端的用户也大有人在。但习惯了WEB开发和简单UI开发的程序员却在这些协议面前迷糊了。

.net的System.Net.Sockets命名空间封装了大量Socket类。使用此命名空间可以通过简单的方法进行复杂的Sockets连接、通迅。下面我就一步步教大家建立一个基于System.Net.Sockets的通用类库,并基于此举几个例子说明如何使用这个类库。

 

1、  首先建立一个类库项目。项目命名为 SocketLibrary,并删除自动生成的Class1.cs


2、  在SocketLibrary中添加类:SocketFactory.cs

3、  在默认解决方案中增加一个Windows项目SocketServerTest用于测试服务器端。

并添加对SocketLibrary的引用。将此项目设为启动项目

4、  在SocketLibrary项目中新建类Connection。表示一个连接,增加两个属性NetWorkStream和ConnectionName。分别表示一个连接的名字和它包含的NetWorkStream。源代码如下:

 

 1 using System;
 3 using System.Net;
 5 using System.Net.Sockets;
 6
 7  
 8
 9 namespace SocketLibrary
10
11 {
12
13     public class Connection
14
15     {
16
17         public NetworkStream NetworkStream {
18
19              get{return _networkStream;}
20
21              set{_networkStream = value;}
22
23         }

24
25         private NetworkStream _networkStream;
26
27         public string ConnectionName {
28
29              get{return _connectionName;}
30
31              set{_connectionName = value;}
32
33         }

34
35         private string _connectionName;
36
37         public Connection(NetworkStream networkStream,string connectionName)
38
39         {
40
41              this._networkStream = networkStream;
42
43              this._connectionName = connectionName;
44
45         }

46
47         public Connection(NetworkStream networkStream):this(networkStream,string.Empty) {
48
49         }

50
51     }

52
53}

54

 

5、  新建一个继承自CollectionBase的类ConnectionCollection。用于保存Connection集合。

 1 using System;
 2
 3  
 4
 5 namespace SocketLibrary  {
 6
 7     public class ConnectionCollection:System.Collections.CollectionBase {
 8
 9         public ConnectionCollection() {
10
11              
12
13         }

14
15         public void Add(Connection value) {
16
17              List.Add(value); 
18
19         }

20
21         public Connection this[int index] {
22
23              get {
24
25                   return List[index] as Connection;    
26
27              }

28
29              set{
30
31                   List[index] = value;
32
33              }

34
35         }

36
37         public Connection this[string connectionName] {
38
39              get {
40
41                   foreach(Connection connection in List) {
42
43                       if(connection.ConnectionName == connectionName)
44
45                            return connection;
46
47                   }

48
49                   return null;
50
51              }

52
53         }

54
55     }

56
57}

58

6、   新建一个类,名字为Server,用于侦听网络连接。

 1 using System;
 2
 3 using System.Net;
 4
 5 using System.Net.Sockets;
 6
 7  
 8
 9 namespace SocketLibrary
10
11 {
12
13     public class Server
14
15     {
16
17         public ConnectionCollection Connections {
18
19              get{return _connections;}
20
21              set{_connections = value;}
22
23         }

24
25         private ConnectionCollection _connections;
26
27 
28
29         private TcpListener _listener;
30
31         public Server(TcpListener listener)
32
33         {
34
35              this._connections = new ConnectionCollection();
36
37              this._listener = listener;
38
39         }

40
41         public void Start() {
42
43              while(true{
44
45                   if(_listener.Pending()) {
46
47                       TcpClient client = _listener.AcceptTcpClient();
48
49                       NetworkStream stream = client.GetStream();
50
51                       this._connections.Add(new Connection(stream));
52
53                   }

54
55              }
    
56
57         }

58
59     }

60
61}

62

7、   在SocketFactory中声明一个私有变量

System.Threading.Thread _serverListenThread;

8、  在SocketFactory类中加入StartServer方法。当执行此方法时,初始化_ serverListenThread并在此线程中开始侦听网络连接

 1 public  void StartServer( int port)  {
 2
 3              TcpListener listener = new TcpListener(IPAddress.Any, port);
 4
 5              listener.Start();
 6
 7 
 8
 9              Server server = new Server(listener);
10
11              _serverListenThread = new System.Threading.Thread(new System.Threading.ThreadStart(server.Start));
12
13              _serverListenThread.Start();
14
15}

16

9、   下面我们来测试此线程是否工作。

在SocketServerTest的Form1的Form1_Load事件中加入如下代码。

1 SocketLibrary.SocketFactory factory =  new SocketLibrary.SocketFactory();
2
3 factory.StartServer(1979);
4

运行程序,可以看出Form1显示出来了。但我们并没有看到监听启动。这是由于我们的监听是在另外一个线程里运行的。我们可以在Server类的Start()函数中加入断点


再次执行程序。可以看到程序会运行到断点处。即开始监听网络连接了。

 

 

10、              下面我们另外启动一个VS.NET2003实例,建立一个项目SocketClientTest,并通过添加已存在的项目增加SocketLibrary,增加对此项目的引用。

 

11、              新建一个Client类。并写上以下源代码

 1 using System;
 2
 3 using System.Net;
 4
 5 using System.Net.Sockets;
 6
 7  
 8
 9 namespace SocketLibrary
10
11 {
12
13 
14
15     public class Client
16
17     {
18
19         public const int CONNECTTIMEOUT = 10;
20
21         public Connection _connection;
22
23         public Client()
24
25         {
26
27              
28
29         }

30
31         public static Connection StartClient(IPAddress ipaddress,int port) {
32
33              TcpClient client = new TcpClient();
34
35              client.SendTimeout = CONNECTTIMEOUT;
36
37              client.ReceiveTimeout = CONNECTTIMEOUT;
38
39 
40
41              client.Connect(ipaddress,port);
42
43         }

44
45     }

46
47}

48

在SocketFactory中加入StartClient函数

1 public Connection StartClient(IPAddress ip, int port)
2
3 {
4
5     return Client.StartClient(ip,port);
6
7}

8

 

在SocketClient的Form1的Form1_Load中加入以下代码


插入断点。开始调试执行。当执行取最后一句时。我们看到_connection已经连接成功。

 

好了,现在我们的客户端已经连接上服务器,并可以发送消息了。但现在我们还没有如何发送消息的方法。我们在SocketFactory中增加一个发消息的静态方法。并且声明一个编码类型的静态变量

public  static System.Text.Encoding DefaultEncoding = 

System.Text.Encoding.GetEncoding("GB2312");

public  static  void SendMessage( string message,Connection connection)  {

     byte[] buffer = DefaultEncoding.GetBytes(message);

     connection.NetworkStream.Write(buffer,0,buffer.Length);

}

现在我们可以用这个函数发消息给服务器端了。


我们看到消息发送成功,但服务器端没有任何反应。这是因为我们还没有在服务器端侦听消息。在Server类中增加如下代码

加入开始侦听网络流的线程

public  void Listenning()  {

     while(true{

         System.Threading.Thread.Sleep(200);

         foreach(Connection connection in this._connections) {

              if(connection.NetworkStream.CanRead && connection.NetworkStream.DataAvailable) {

                   byte[] buffer = new byte[1024];

                   int count = connection.NetworkStream.Read(buffer,0,buffer.Length);

                   Console.Write(SocketFactory.DefaultEncoding.GetString(buffer,0,count));

              }


         }


     }


}

 

 1 public  void StartListen()  {
 2
 3     _listenningthread = new System.Threading.Thread(new System.Threading.ThreadStart(Listenning));
 4
 5     _listenningthread.Start();
 6
 7}

 8
 9 private System.Threading.Thread _listenningthread;
10

再在SocketFactory的StartServer中加入以下代码,以开始侦听网络流。


好。我们再启动SocketServerTest。并运行SocketClientTest。现在在SocketServerTest的控制台可以看到如下输出:

 

也即服务器收到了客户端发来的Hello Server的消息。

这一章我们就到这里。下一章我们继续讲如何重构这一章的代码,并继续深入的讲如何定义协议以及如何使用这些协议收发消息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值