C# Socket详细剖析

开发 后端
这里介绍C# Socket用法基本上不算很复杂,只是不知道托管之后的Socket有没有其他性能或者安全上的问题。在C#里面能找到的最底层的操作也就是socket了,概念不做解释。

C#语言还是比较常见的东西,这里我们主要介绍C# Socket,包括介绍建立本机的IPEndPoint对象等方面。

其实只要用到Socket联接,基本上就得使用Thread,是交叉使用的。C# Socket用法基本上不算很复杂,只是不知道托管之后的Socket有没有其他性能或者安全上的问题。在C#里面能找到的***层的操作也就是socket了,概念不做解释。

程序模型如下:
◆WinForm程序 : 启动端口侦听;监视Socket联接情况;定期关闭不活动的联接;
◆Listener:处理Socket的Accept函数,侦听新链接,建立新Thread来处理这些联接(Connection)。
◆Connection:处理具体的每一个联接的会话。

1:WinForm如何启动一个新的线程来启动Listener:

  1.  //start the server  
  2. private void btn_startServer_Click(object sender, EventArgs e)  
  3. {  
  4. //this.btn_startServer.Enabled = false;  
  5. Thread _createServer = new Thread(new ThreadStart(WaitForConnect));  
  6. _createServer.Start();  
  7. }  
  8. //wait all connections  
  9. private void WaitForConnect()  
  10. {  
  11. SocketListener listener = new SocketListener(Convert.ToInt32(this.txt_port.Text));  
  12.  listener.StartListening();  

因为侦听联接是一个循环等待的函数,所以不可能在WinForm的线程里面直接执行,不然Winform也就是无法继续任何操作了,所以才指定一个新的线程来执行这个函数,启动侦听循环。
这一个新的线程是比较简单的,基本上没有启动的参数,直接指定处理函数就可以了。

2:Listener如何启动循环侦听,并且启动新的带有参数的线程来处理Socket联接会话。

先看如何建立侦听:(StartListening函数)

  1. // Create a TCP/IP socket.  
  2. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
  3. // Bind the socket to the local endpoint andlisten for incoming connections.  
  4. try  
  5. {  
  6. listener.Bind(localEndPoint);  
  7. listener.Listen(20);//20 trucks  
  8.  
  9. // Start listening for connections.  
  10. while (true)  
  11. {  
  12. // here will be suspended while waiting for a new connection.  
  13. Socket connection = listener.Accept();  
  14. Logger.Log("Connect", connection.RemoteEndPoint.ToString());//log it, new connection  
  15. ……  
  16. }  
  17. }  
  18. …… 

基本步骤比较简单:
建立本机的IPEndPoint对象,表示以本机为服务器,在指定端口侦听;然后绑定到一个侦听Socket上;进入while循环,等待新的联接;如果有新的联接,那么建立新的socket来对应这个联接的会话。

值得注意的就是这一句联接代码:listener.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。

新的联接Socket建立了(Accept之后),对于这些新的socket该怎么办呢?他们依然是一个循环等待,所以依然需要建立新的Thread给这些Socket去处理会话(接收/发送消息),而这个Thread就要接收参数了。Thread本身是不能接收参数的,为了让它可以接收参数,可以采用定义新类,添加参数作为属性的方法来解决。因为每一个Socket是一个Connection周期,所以我定义了这么一个类public class Connection。这个类至少有这样一个构造函数public Connection(Socket socket); 之所以这么做,就是为了把Socket参数传给这个Connection对象,然后好让Listener启动这个Thread的时候,Thread可以知道他正在处理哪一个Socket。具体处理的方法:(在Listener的StartListening函数,ocket connection = listener.Accept();之后)

  1. Connection gpsCn = new Connection(connection);  
  2. //each socket will be wait for data. keep the connection.  
  3. Thread thread = new Thread(new ThreadStart(gpsCn.WaitForSendData));  
  4. thread.Name = connection.RemoteEndPoint.ToString();  
  5. thread.Start(); 

3:Connection的会话处理
建立了新的Connection(也就是socket),远程就可以和这个socket进行会话了,无非就是send和receive。现在先看看怎么写的这个线程运行的Connection. WaitForSendData函数

  1. while (true)  
  2. {  
  3. bytes = new byte[1024];  
  4. string data = "";  
  5. //systm will be waiting the msg of receive envet. like Accept();  
  6. //here will be suspended while waiting for socket income msg.  
  7. int bytesRec = this._connection.Receive(bytes);  
  8. _lastConnectTime = DateTime.Now;  
  9. if (bytesRec == 0)//close envent  
  10. {  
  11. Logger.Log("Close Connection", _connection.RemoteEndPoint.ToString());  
  12. break;  
  13. }  
  14. data += Encoding.ASCII.GetString(bytes, 0, bytesRec);  
  15. //…….handle your data.  

可以看到这个处理的基本步骤如下:执行Receive函数,接收远程socket发送的信息;把信息从字节转换到string;处理该信息,然后进入下一个循环,继续等待C# Socket发送新的信息。

值得注意的有几个:
1:Receive函数。这个函数和Listener的Accept函数类似。在这个地方等待执行,如果没有新的消息,这个函数就不会执行下一句,一直等待。
2:接收的是字节流,需要转化成字符串
3:判断远程关闭联接的方式
4:如果对方的消息非常大,还得循环接收这个data。

【编辑推荐】

  1. C#类和结构简单介绍
  2. C# explicti和implicit详解
  3. C#编写ActiveX控件详细介绍
  4. C# StringBuilder和String浅析
  5. C#别名指示符学习经验
责任编辑:佚名 来源: cnblogs
相关推荐

2009-09-11 11:17:04

C#引用类型

2009-09-03 16:58:49

C#内存管理

2009-08-31 17:26:32

C#异常处理

2009-09-18 10:00:17

C#数组操作

2009-08-27 17:51:34

C#匿名方法

2009-09-04 11:06:40

C#访问修饰符

2009-08-31 16:29:21

C#控制输入法

2009-08-28 15:38:49

C#实现断点续传

2009-09-07 13:42:56

C# Pop3类

2009-09-07 14:29:52

C# ServiceC

2009-09-01 16:29:03

QuickSort C

2009-08-18 16:45:40

C# Raw Sock

2009-08-03 16:45:02

C#异步Socket

2009-09-11 11:09:36

C#引用类型

2009-09-01 11:04:59

C#调用扩展方法

2009-08-27 16:29:18

C#动态编译

2009-09-02 18:14:33

C# WebClien

2009-08-28 10:44:46

C#字符数组转换

2009-08-10 16:30:56

C# BitmapDa

2009-08-12 15:34:40

C# DBNull
点赞
收藏

51CTO技术栈公众号