客户端和服务端之间的通信(TCP)
和上篇的 客户端和服务端之间的通信(UDP)程序类似:http://www.cnblogs.com/Shang0109/archive/2012/07/29/2614176.html
Socket最初应用于Unix当中,代表了一种文件描述符(在Unix中一切都是以文件为单位的)。在Windows当中则用于描述网路的访问,程序员通过Socket来发送和接收网路中的信息,因此我们可以把它理解为是一个跟网卡交互的API接口函数。
Socket访问网络的要素:
1、本机的IP和Port端口(Socket只有与某一个IP和Port绑定,才能偶发挥强大的作用)
2、必须指定通讯协议如:TCP和UDP。
在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务
通过一个简单的实例来了解一下Socket在TCP协议下的基本通讯。
在程序当中使用到Socket时,需要首先添加“using System.Net; 和using System.Net.Sockets;” 两个引用
一、新建一个控制台应用程序:Server;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace Server { class Program { //1、要使用 Socket 发送和接收数据,必须首先使用 AddressFamily、SocketType 及 ProtocolType 创建它 //2、SocketType 有时会隐式指示在 AddressFamily 中使用哪个 ProtocolType。例如,当 SocketType 为 Dgram 时,ProtocolType 始终为 Udp。 // 当 SocketType 为 Stream 时,ProtocolType 始终为 Tcp。如果试图使用不兼容的组合创建 Socket,则 Socket 将引发 SocketException。 static void Main(string[] args) { //第一步,定义一个Socket套接字 Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //SocketType.Stream支持可靠、双向、基于连接的字节流,而不重复数据,也不保留边界。此类型的 Socket 与单个对方主机进行通信,并且在通信开始之前需要远程主机连接。Stream 使用传输控制协议 (Tcp) ProtocolType 和 InterNetworkAddressFamily。 //AddressFamily.InterNetwork表示使用的IP地址是4段的, //第二步,绑定ip和端口 IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050); s.Bind(ipep); //第三步,通知TCP,服务器已经就绪 s.Listen(0);//TCP是面向连接的,需要用Listen()方法监听一下网络上是否有人发送东西过来。 //而UDP则不需要,UDP是无连接的,来者不拒。 Console.WriteLine("服务器已启动!"); //第四步,等待客户端的连接请求 Socket client = s.Accept(); //TCP情况下,如果监听到一个连接,就可以使用Accept()方法进行接收这个连接,然后执行Send()或者Receive() //UDP则不需要Accept(),直接用SendTo/ReceiveFrom来执行操作。 //UDP不建立连接,所以发送前并不知道对方的IP和端口,因此需要指定一个发送的节点才能进行正常的发送和接收。(参照上篇UDP:http://www.cnblogs.com/Shang0109/archive/2012/07/29/2614176.html) Console.WriteLine("有客户端:" + client.RemoteEndPoint.ToString() + "连接"); byte[] recv = new byte[1024]; //定义一个byte类型的数组用于接收信息 //接收客户端的信息,并保存到byte数组中(Receive()使用指定的 SocketFlags,从绑定的 Socket 接收数据,将数据存入接收缓冲区。) //SocketFlags:指定套接字的发送和接收行为。None:不对此调用使用标志。 int bytes = client.Receive(recv, recv.Length, SocketFlags.None); //将byte数组转换成可读的string string receive = Encoding.ASCII.GetString(recv, 0, bytes);//进接收的信息转换成相应的字符串 Console.WriteLine("接收到一条信息:" + receive); string sendString = "hello,this is a string from server"; byte[] send = Encoding.ASCII.GetBytes(sendString); client.Send(send, send.Length, SocketFlags.None); client.Close(); s.Close();//关闭套接字,服务停止 Console.ReadLine(); } } }
二、新建一个控制台应用程序:Client;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace Client { class Program { static void Main(string[] args) { //客户端和服务端类似 //第一步:建立套接字 Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //第二步:将套接字于远程主机连接 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);//127.0.0.1指定本机的IP地址 s.Connect(ipep);//连接服务器 //第三步:发送信息 string sendString = "this is a string to send"; byte[] send = Encoding.ASCII.GetBytes(sendString);//将发送的信息转换成byte类型数组 s.Send(send, send.Length, SocketFlags.None); byte[] recv = new byte[1024]; int length = s.Receive(recv, recv.Length, SocketFlags.None); string receive = Encoding.ASCII.GetString(recv, 0, length); Console.WriteLine("从服务器端接收到一条信息:" + receive); s.Close(); Console.ReadLine(); } } }
三、运行:先启动服务器,之后运行客户端程序。