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