C# Socket 发送&接收&返回

             因为工作比较忙,好久没有写过博客了,最近因项目需求,需要用到Socket来进行通信,简单写了几个例子,记录一下,代码很简单,无非就是接收与发送,以及接收到数据后返回一个自定义信息,也可以说是发送。

             先来简单写一个接收端的样例,因为Socket需要监听主机上的某个可用端口,在监听开始之前并不是很清楚要监听的某个端口是否被占用,可以在CMD或Powershell中输入netstat -ano 进行查看,但这样的话在每次使用一个端口之前都需要这样操作,相对来讲比较繁琐。当然除此之外我们也可以通过 IPGlobalProperties来获取本机的网络连接的信息,并通过GetActiveTcpListeners找到已用端口,进而可以知道所需的端口是否已被占用,完成代码如下:

 1       public static bool PortIsUse(int port)
 2         {
 3             bool isUse = false;
 5             IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
 6             IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();//找到已用端口
 8             foreach (IPEndPoint endPoint in ipEndPoints)
 9             {
10                 if (endPoint.Port == port)//判断是否存在
11                 {
12                     isUse= true;
13                     break;
14                 }
15             }
16             return isUse;
17         }

              在做好准备工作后,开始来写接收端代码,首先得定义一个TcpListener对象来监听本地的某个端口,比如我要监听本地的1111端口那么代码可以写为:

     TcpListener tcpl = new TcpListener(new IPAddress(new byte[] { 127, 0, 0, 1 }), 1111);//定义一个TcpListener对象监听本地的1111端口

       在监听之前先调用之前写的方法,检查一下端口是否被占用,在定义好TcpListener后就可以调用该类的Start方法开始监听,接收端完整代码如下:

          TcpListener tcpl = new TcpListener(new IPAddress(new byte[] { 127, 0, 0, 1 }), 1111);//定义一个TcpListener对象监听本地的1111端口
          tcpl.Start();//监听开始
              while (true)
              {
                  Socket s = tcpl.AcceptSocket();//挂起一个Socket对象
                  string remote = s.RemoteEndPoint.ToString();//获取发送端的IP及端口转为String备用
                  Byte[] stream = new Byte[1024];
                  s.Receive(stream);//接收发送端发过来的数据,写入字节数组
                 //BGW_Handle.ReportProgress(1, "接收来自[" + remote + "]信息");
                 string _data = Encoding.UTF8.GetString(stream);//将字节数据数组转为String
                 s.Send(stream);//将接收到的内容,直接返回接收端
                 s.Shutdown(SocketShutdown.Both);
             }
             tcpl.Stop();//停止监听

        接收端代码并没有很多,看起来也不是很复杂,在启动监听后,挂起一个Socket,并等待消息到达,在收到消息时,使用Receive方法将收到的消息写入到Byte数组中,并在后续中直接将所收到的内容,转为String,此时调用Socket的Send方法,将收到的数据直接回送给发送端,值得注意的在上述代码中我使用了一个死循环while(true),在实际项目中,要考虑到这个循环所带来的一系列问题,如阻塞主线程,UI线程,检测到后续代码无法访问等,在应用到实际项目时,还要做一定的修改。             

       在接收端准备好后,开始来写发送端代码,因为发送端不需要监听端口,所以就不用再定义一个TcpListener对象,也不需要检查所用的端口是否已被占用,此时我们可以直接初始化一个Socket及将要连接的IPEndPoint对象,在定义Socket时指定其寻址方案为AddressFamily.InterNetwork,即通过IPV4来寻址,并指定类型为SocketType.Stream,即开始通信之前需要远程主机的连接。同时指定Socket类支持的协议为TCP,代码为:

               IPAddress ip = IPAddress.Parse("127.0.0.1");//接收端所在IP
               IPEndPoint ipEnd = new IPEndPoint(ip, 1111);//接收端所监听的接口
               Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化一个Socket对象

       在初始化完Socket对象后,即可使用Socket的Connect方法,尝试连接,些前已定的接收端的地址及端口,在连接成功后,即可开始发送数据,并尝试接收返回的数据,完整代码如下:

             IPAddress ip = IPAddress.Parse("127.0.0.1");//接收端所在IP
             IPEndPoint ipEnd = new IPEndPoint(ip, 1111);//接收端所监听的接口
             Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化一个Socket对象
             try
             {
                 socket.Connect(ipEnd);//连接指定IP&端口
             }
             catch (SocketException e)
             {
                Console.WriteLine("连接失败");
                 Console.WriteLine(e.ToString());
                 return;
             }
            socket.Send(Encoding.UTF8.GetBytes("1234567890"));//发送数据
           while (true)//定义一个循环接收返回数据
            {
                byte[] data = new byte[1024];
                socket.Receive(data);//接收返回数据
                 string  stringData = Encoding.UTF8.GetString(data);
                if (!string.IsNullOrWhiteSpace(stringData))
                {
                    Console.Write(stringData);
                    break;
                }
            }
socket.Shutdown(SocketShutdown.Both); socket.Close();//关闭Socket

                      从上面代码来看,发送端的代码也并不是很繁杂,当然上面所写的代码也只是实现了几个简单的发送与接收的功能。到这里为止一个简单的发送与接收及收接后返回就已完成了,上述代码若有何不当之处,可在评论中提出来。