TCP/IP .Net Socket 编程(服务端和客户端)

其实网上已经有很多关于socket编程了,基本上大学还是学习,第一个通信的例子应该就是基于Socket通信的知识。

大学天天背TCP/IP 七层,四层协议的,我现在也不一定一口全部说出来。

啥事儿,不说,上来就干,咱先来个客户端,再来个服务端。.

最后,看下效果,就OK。其他详细细节,可以MSDN查看。

服务端Socket实现

新创建一个控制台项目,大致如下

TCP/IP .Net Socket 编程(服务端和客户端)

创建服务

        public NetServer(int port)
        {
            this.port = port;
            ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            LocalAddress = GetLocalAddress().ToString();
            ServerSocket.Bind(new IPEndPoint(GetLocalAddress(), port));
        }

启动服务

        public void Start()
        {
            ServerSocket.Listen(50);
            //负责监听客户端的线程:创建一个监听线程  
            Thread threadwatch = new Thread(watchconnecting);
            //将窗体线程设置为与后台同步,随着主线程结束而结束  
            threadwatch.IsBackground = true;
            //启动线程     
            threadwatch.Start();
            Console.WriteLine(LocalAddress + " : " + port);
            Console.WriteLine("开启监听。。。");
            Console.WriteLine("请勿输入任何数据,会停止服务!!!");
        }

监听客户端发过来的请求

 //监听客户端发来的请求  
        public void watchconnecting()
        {
            Socket connection = null;
            //持续不断监听客户端发来的请求     
            while (true)
            {
                try
                {
                    connection = ServerSocket.Accept();
                }
                catch (Exception ex)
                {
                    //提示套接字监听异常     
                    Console.WriteLine(ex.Message);
                    break;
                }
                try
                {
                    //获取客户端的IP和端口号  
                    IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
                    int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port;

                    //客户端网络结点号  
                    string remoteEndPoint = connection.RemoteEndPoint.ToString();
                    //显示与客户端连接情况
                    Console.WriteLine("成功与" + remoteEndPoint + "客户端建立连接!");

                    //IPEndPoint netpoint = new IPEndPoint(clientIP,clientPort); 
                    IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint;

                    //创建一个通信线程      
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(recv);
                    Thread thread = new Thread(pts);
                    //设置为后台线程,随着主线程退出而退出 
                    thread.IsBackground = true;
                    //启动线程     
                    thread.Start(connection);
                }
                catch (Exception)
                { }
            }
        }

接收客户端的信息,并原文返回,

/// <summary>
        /// 接收客户端发来的信息,客户端套接字对象
        /// </summary>
        /// <param name="socketclientpara"></param>    
        public void recv(object socketclientpara)
        {
            Socket socketServer = socketclientpara as Socket;
            try
            {
                while (true)
                {
                    //创建一个内存缓冲区,其大小为1024*1024字节  即1M     
                    byte[] arrServerRecMsg = new byte[1024 * 1024];
                    //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度    
                    try
                    {
                        int length = socketServer.Receive(arrServerRecMsg);
                        //Console.WriteLine(length);
                        //接受多少,发送多少
                        if (length > 0)
                        {
                            byte[] b = new byte[length];
                            Array.Copy(arrServerRecMsg, b, b.Length);

                            var ret = socketServer.Send(b);
                            //将发送的字符串信息附加到文本框txtMsg上        
                            Console.WriteLine("客户端:" + socketServer.RemoteEndPoint + "发送客户端状态:" + ret + "返回结果:" + Encoding.UTF8.GetString(b) + ",time:" + DateTime.Now.ToString());
                        }
                        else
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        //提示套接字监听异常  
                        Console.WriteLine("客户端" + socketServer.RemoteEndPoint + "已经中断连接" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace + "\r\n");
                        //关闭之前accept出来的和客户端进行通信的套接字 
                        socketServer.Close();
                        break;
                    }
                }
                //提示套接字监听异常  
                Console.WriteLine("客户端" + socketServer.RemoteEndPoint + "已经中断连接");
                //关闭之前accept出来的和客户端进行通信的套接字 
                socketServer.Close();
            }
            catch (Exception)
            {

            }
        }

如何获取到一个本地地址

        public IPAddress GetLocalAddress()
        {
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            int len = interfaces.Length;

            for (int i = 0; i < len; i++)
            {
                NetworkInterface ni = interfaces[i];
                if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                {
                    if (ni.Name == "本地连接")
                    {
                        IPInterfaceProperties property = ni.GetIPProperties();
                        foreach (UnicastIPAddressInformation ip in
                            property.UnicastAddresses)
                        {
                            if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                            {
                                return  ip.Address;
                            }
                        }
                    }
                }

            }
            return IPAddress.Loopback; ;
        }

启动服务实例

        static void Main(string[] args)
        {
            Console.Title = "蓝创精英团队 NetServer 服务端";
            Console.WriteLine("请输入本地需要监听的端口号:");
            var read = Console.ReadLine();
            NetServer server = new NetServer(read);
            server.Start();
            Console.WriteLine("服务启动,测试中!!");
            Console.ReadLine();
        }

这个时候socket的服务端就已经创建,并启动了。

然后等客户端的连接,来,我么接下来搞客户端。

创建客户端

TCP/IP .Net Socket 编程(服务端和客户端)

连接服务端

        /// <summary>
        /// 客户端
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="Port"></param>
        public netClient(string ip, int Port)
        {
            _ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            this.ipAddress = ip;
            this.Port = Port;
        }

启动连接服务端

        public void Start()
        {
            _ClientSocket.Connect(new IPEndPoint(IPAddress.Parse(this.ipAddress), this.Port));//通过IP和端口号来定位一个所要连接的服务器端
                                                                                              //客户端网络结点号  
            remoteEndPoint = _ClientSocket.RemoteEndPoint.ToString();
            LocalEndPoint = _ClientSocket.LocalEndPoint.ToString();
            Console.WriteLine($"远端地址:{remoteEndPoint} 本端地址:{LocalEndPoint}");
            threadReceive = new Thread(Receive);
            threadReceive.IsBackground = true;
            threadReceive.Start();
            IsRun = true;
        }

接收服务端发送过来的消息

        /// <summary>
        /// 消息的接收
        /// </summary>
        private void Receive()
        {
            byte[] TempData = new byte[1024 * 10];
            while (IsRun)
            {
                //传递一个byte数组,用于接收数据。length表示接收了多少字节的数据
                int length = _ClientSocket.Receive(TempData);
                if (length == 0)
                {
                    IsRun = false;
                    Console.WriteLine("服务器断开链接");
                    break;
                }
                else
                {
                    string message = Encoding.UTF8.GetString(TempData, 0, length);//只将接收到的数据进行转化
                    Console.WriteLine($"远端地址:{remoteEndPoint} 本端地址:{LocalEndPoint} 获取到的数据:{message}");
                }
            }
        }

发送消息到服务端

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public int Send(string data)
        {
            return _ClientSocket.Send(Encoding.UTF8.GetBytes(data));
        }

启动客户端实例

        static void Main(string[] args)
        {
            Console.Title = "蓝创精英团队 NetServer 客户端";
            netClient client = null;
            bool isTrue = true;
            while (isTrue)
            {
                Console.WriteLine("请输入本地需要连接的ip:端口号:");
                var read = Console.ReadLine();
                if (read.IndexOf(":") > -1)
                {
                    var data = read.Split(':');
                    var ip = data[0];
                    var port = int.Parse(data[1]);
                    client = new netClient(ip, port);
                    client.Start();
                    break;
                }
                else
                {
                    continue;
                }
            }
            string message = string.Empty;
            while ((message = Console.ReadLine()) != "exit")
            {
                client.Send(message);
            }
            Console.WriteLine("客户端启动,测试中!!");
            Console.ReadLine();
        }

实际案例

先启动服务端,输入端口号 9999

TCP/IP .Net Socket 编程(服务端和客户端)

TCP/IP .Net Socket 编程(服务端和客户端)

然后启动 客户端

TCP/IP .Net Socket 编程(服务端和客户端)

TCP/IP .Net Socket 编程(服务端和客户端)

输入127.0.0.1:9999 连接服务端

连接成功后,服务端会收到客户端建立的连接。

TCP/IP .Net Socket 编程(服务端和客户端)

然后,客户端给服务端发送消息。

TCP/IP .Net Socket 编程(服务端和客户端)

可以看到,效果还是很明显的。

需要注意的

对粘包粘包等都没有处理,算是简单的Demo样例,用起来处理简单的问题还是很方便的。

结束

很多时候,想直接搞个服务,又不想用网上的,找又找半天。

索性,就自己写了个,方便自己用。

平时也出力不少。^_^

代码地址

https://github.com/kesshei/NetServerDemo.git

https://gitee.com/kesshei/NetServerDemo.git