#Sample of the Day Socket Communication

[Sample of Mar 21th] Socket communication in C# and VB

注:随笔是2012年3月份写的,当时不知道怎么就保存成了草稿而一直没有发布,现在(2013年6月)发布一下,算是纪念吧,不过,我把发布时间改成了2012年

早就知道有 Socket 编程这样的方式,但是一直没怎么真正用过,借着 Sample of the Day 的机会,学习一下。以下的文字大部分来自 MSDN,我自己的标记为蓝色。

Sockets are an application programming interface (API) in an operating system, used for in inter-process communication. Sockets constitute a mechanism for delivering incoming data packets to the appropriate application process or thread, based on a combination of local and remote IP addresses and port numbers. Each socket is mapped by the operational system to a communicating application process or thread.

.NET supplies a Socket class which implements the Berkeley sockets interface. It provides a rich set of methods and properties for network communications. The Socket class allows you to perform both synchronous and asynchronous data transfer using any of the communication protocols listed in the ProtocolType enumeration.

In synchronous mode, calls to functions that perform network operations (such as Send and Receive) wait until the operation completes before returning control to the calling program.

In asynchronous mode, these calls return immediately.

看起来似乎异步 asynchronous 的方式更好,只是不知道能否保证传递正确。

Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

AddressFamily 包括多种地址类型,包括 InterNetwork(IP v4),InterNetworkV6,甚至还有 Irda,NetBios 等不那么常见的地址结构(addressing schema)

SocketType 包括多种 Socket 类型,比较常用的应该是 Stream 和 Dgram,两者都是在 InterNetwork 地址结构下面,一个使用 TCP 协议,另一个使用 UDP 协议。

Stream  Supports reliable, two-way, connection-based byte streams without the duplication of data and without preservation of boundaries. A Socket of this type communicates with a single peer and requires a remote host connection before communication can begin. Stream uses the Transmission Control Protocol (Tcp) ProtocolType and the InterNetwork AddressFamily.
Dgram  Supports datagrams, which are connectionless, unreliable messages of a fixed (typically small) maximum length. Messages might be lost or duplicated and might arrive out of order. A Socket of type Dgram requires no connection prior to sending and receiving data, and can communicate with multiple peers. Dgram uses the Datagram Protocol (Udp) and the InterNetwork AddressFamily.

ProtocolType 包括 TCP、UDP,以及 IP、IPv6、Icmp、Ipx 等多种协议。

客户端代码相对来说比较简单:

 1 #region Using directives
2 using System;
3 using System.Text;
4 using System.Net;
5 using System.Net.Sockets;
6 using System.Security.Permissions;
7 #endregion
8
9 public class Program
10 {
11 static void Main(string[] args)
12 {
13 // Receiving byte array
14 byte[] bytes = new byte[1024];
15 try
16 {
17 // Create one SocketPermission for socket access restrictions
18 SocketPermission permission = new SocketPermission(
19 NetworkAccess.Connect, // Connection permission
20 TransportType.Tcp, // Defines transport types
21 "", // Gets the IP addresses
22 SocketPermission.AllPorts // All ports
23 );
24
25 // Ensures the code to have permission to access a Socket
26 permission.Demand();
27
28 // Resolves a host name to an IPHostEntry instance
29 IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
30
31 // Gets first IP address associated with a localhost
32 IPAddress ipAddr = ipHost.AddressList[0];
33
34 // Creates a network endpoint
35 IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 4510);
36
37 // Create one Socket object to setup Tcp connection
38 Socket sender = new Socket(
39 ipAddr.AddressFamily,// Specifies the addressing scheme
40 SocketType.Stream, // The type of socket
41 ProtocolType.Tcp // Specifies the protocols
42 );
43
44 sender.NoDelay = false; // Using the Nagle algorithm
45
46        // Establishes a connection to a remote host
47 sender.Connect(ipEndPoint);
48 Console.WriteLine("Socket connected to {0}",
49 sender.RemoteEndPoint.ToString());
50
51 // Sending message
52        //<Client Quit> is the sign for end of data
53 string theMessage = "Hello World!";
54 byte[] msg = Encoding.Unicode.GetBytes(theMessage +"<Client Quit>");
55
56 // Sends data to a connected Socket.
57 int bytesSend = sender.Send(msg);
58
59 // Receives data from a bound Socket.
60 int bytesRec = sender.Receive(bytes);
61
62 // Converts byte array to string
63 theMessage = Encoding.Unicode.GetString(bytes, 0, bytesRec);
64
65 // Continues to read the data till data isn't available
66 while (sender.Available > 0)
67 {
68 bytesRec = sender.Receive(bytes);
69 theMessage += Encoding.Unicode.GetString(bytes, 0, bytesRec);
70 }
71 Console.WriteLine("The server reply: {0}", theMessage);
72
73 // Disables sends and receives on a Socket.
74 sender.Shutdown(SocketShutdown.Both);
75
76 //Closes the Socket connection and releases all resources
77 sender.Close();
78 }
79 catch (Exception ex)
80 {
81 Console.WriteLine("Exception: {0}", ex.ToString());
82 }
83
84 Console.Read();
85 }
86 }

这段程序相对来说比较简单,但是也有几个有意思的地方。

第一个就是前面关于 SocketPermission 的处理,调用了父类CodeAccessPermission.Demand() 方法。

CodeAccessPermission.Demand() : Forces a SecurityException at run time if all callers higher in the call stack have not been granted the permission specified by the current instance.

第二个是得到主机的 IP 地址部分。System.Net.Dns 这个静态类还真是挺有用的,可以得到主机名(hostname)和 IP地址。只不过想得到主机IP地址似乎必须先得到主机名,然后再调用 Dns.GetHostAddresses(hostname),而且返回的是一个 IPAddress 的数组。

第三个是关于 Socket.Avaliable 属性,表示:Gets the amount of data that has been received from the network and is available to be read.

 



 

posted on 2012-03-24 15:43  zhaorui  阅读(261)  评论(0编辑  收藏  举报

导航