遑盲 发表于 2025-6-2 00:33:46

C# Socket教程入门,Socket的使用方法,附可执行Demo

核心:

在服务器端和客户端的两个Socket实例,共同维持一个连接,而我们还需要一个服务端绑定了特定端口号的固定的serverSocket,用来监听远方clientSocket的申请,并为这个申请建立服务端对应的proxSocket
服务器维护:serverSocket
服务端实例客户端实例关系proxSocketclientSocket一一对应微软官方文档
一、要有服务端

--配置--

1、new Socket
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2、Bind
ServerSocket.Bind(new IPEndPoint(IPAddress.Parse(txtIP), int.Parse(txtPost))); //服务器绑定本机IP和端口
3、Listen
ServerSocket.Listen(10); //最大连接数是10
4、Accept
Socket proxSocket = ServerSocket.Accept(); //监听Socket连接行为,并为监听到的链接创建Socket实例,会阻塞线程直到端口链接
--信息发送与传输--

5、Receive
proxSocket.Receive(data, 0, data.Length, SocketFlags.None); //data是要写入的byte数组,会阻塞线程直到侦听到slientSocket的Send并持续到IO结束
6、Send
proxSocket.Send(result, 0, result.Length, SocketFlags.None); //result是要上传的byte数组
二、还有客户端

--配置--

1、new Socet
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2、Connect
ClientSocket.Connect(new IPEndPoint(IPAddress.Parse(txtIP), int.Parse(txtPort)));//尝试链接服务器的相应IP和端口,连接成功后,服务器端创建一个特定的proxSocket用来进行信息交换
--信息发送与传输--

3
ClientSocket.Receive(data, 0, data.Length, SocketFlags.None);
4
ClientSocket.Send(result, 0, result.Length, SocketFlags.None);
三、简单实现

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace SockerDamo
{
    class SocketServer
    {
      List<Socket> ClientProxSocketList = new List<Socket>();//用于存放客户端链接
      Socket ServerSocket { get; set; }

      public void Start()//创建服务器Socket,开始侦听客户端,并开始循环接收消息
      {
            //1.创建socket对象
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ServerSocket = serverSocket;
            //first is 寻址方式(此处是Ipv4)
            //second is the socket's type
            //And the thrid is the 传输协议

            System.Console.WriteLine("请输入IP地址:");
            String txtIP = Console.ReadLine();

            System.Console.WriteLine("请输入端口号:");
            String txtPost = Console.ReadLine();

            //2.绑定端口IP
            ServerSocket.Bind(new IPEndPoint(IPAddress.Parse(txtIP), int.Parse(txtPost)));
            //socket's Bind action need a IPEndPoint to bind the socket and the computer's ip and post
            //so in the IPEndPoint we need a IPAddress and a int number(Post)


            //3.开始侦听
            ServerSocket.Listen(20);//the number 表示 同时排队的最大限制数量
            //同时来了100个链接请求,只能处理一个链接,队列里面放20个等待链接的客户端,其他的返回错误消息。


            //4.开始接受客户端的链接
            //为了不阻塞主线程,我们应该把以下代码放在一个新的线程(池)中

            try
            {
                System.Console.WriteLine("开始监听链接...");
                Socket proxSocket = ServerSocket.Accept();//这个方法会阻塞当前线程,直到监听到链接
                AppendTextToTxtLog(string.Format("客户端{0}已链接", proxSocket.RemoteEndPoint.ToString()));
                byte[] data = new byte;//用来放数据的数组
                int len;
                while (true)
                {
                  System.Console.WriteLine("请选择模式:");
                  System.Console.WriteLine("0.等待接收消息");
                  System.Console.WriteLine("1.发送消息");
                  string mo = Console.ReadLine();
                  //获取客户端数据并返回读取的字节数,会阻塞当前线程,
                  //当客户端突然掉线,往往会引发异常
                  if (mo == "0")
                  {
                        try
                        {
                            len = proxSocket.Receive(data, 0, data.Length, SocketFlags.None);//往data数组里,从index=0开始,最长写入数据长度为data.Length
                            if (data == 0)
                            {
                              StopConnect(proxSocket);
                            }//正常退出逻辑
                            else if (data == 1)
                            {
                              string str = Encoding.UTF8.GetString(data, 1, len - 1);//在data数组中从0开始,len个数据,转成str
                              AppendTextToTxtLog(string.Format("接收到客户端:{0} 的信息是:{1}", proxSocket.RemoteEndPoint.ToString(), str));
                            }
                        }
                        catch (Exception)
                        {
                            Console.WriteLine("接收数据出错");
                            StopConnect(proxSocket);
                        }
                  }
                  else if (mo == "1")
                  {
                        SendMsg();
                  }
                }
            }
            catch
            {
                AppendTextToTxtLog("出问题啦:您在接收客户端的请求的时候,发生了异常,夭寿啦```");
            }
      }

      private void StopConnect(Socket proxSocket)//停止链接
      {
            try
            {
                if (proxSocket.Connected)
                {
                  proxSocket.Shutdown(SocketShutdown.Both);
                  proxSocket.Close(100);
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("或许没有成功的停止连接" + ex.ToString());
            }
      }

      //发送消息
      private void SendMsg()
      {
            String txtMsg = Console.ReadLine();
            foreach (var proxSocket in ClientProxSocketList)
            {
                if (proxSocket.Connected)
                {
                  byte[] data = Encoding.UTF8.GetBytes(txtMsg);//信息转二进制
                  byte[] result = new byte;//信息的二进制放在1~data.Length
                  result = 1;//第0个位置是标志位,将来我们可以用这个标志位,分辨文件类型,将来用来传文件
                  Buffer.BlockCopy(data, 0, result, 1, data.Length);//把 data从0 转 result从1 长度data.Length
                  proxSocket.Send(result, 0, result.Length, SocketFlags.None);//发送消息
                }
            }
            AppendTextToTxtLog(string.Format("{0}(本机) 的信息是:{1}", ServerSocket.LocalEndPoint.ToString(), txtMsg));
      }

      private void AppendTextToTxtLog(string txt)
      {
            Console.WriteLine(txt);
      }

    }
    class SocketClient
    {
      Socket ClientSocket { get; set; }

      public void Start()//创建客户端Socket,并开始循环接收消息
      {
            #region 获取服务器端口内容
            System.Console.WriteLine("请输入服务器IP:");
            String txtIP = Console.ReadLine();
            System.Console.WriteLine("请输入端口号:");
            String txtPort = Console.ReadLine();
            #endregion
            //客户端链接服务器端
            //1.创建Socket对象
            ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //2.连接服务器端Socket
            try//如果服务器的Listen队列已满,那么就会返回一个异常
            {
                ClientSocket.Connect(new IPEndPoint(IPAddress.Parse(txtIP), int.Parse(txtPort)));
            }
            catch
            {
                System.Console.WriteLine("当前服务器无法连接");
                //Thread.Sleep(1000);
                return;
            }

            //3.接收服务器端消息

            byte[] data = new byte;//传输数据放在这里,这里是256MB = 256 * 1024 KB = 256 * 1024 * 1024Byte
            int len;
            string str;
            string wenJianMing = "";
            while (true)
            {
                System.Console.WriteLine("请选择模式:");
                System.Console.WriteLine("0.等待接收消息");
                System.Console.WriteLine("1.发送消息");
                string mo = Console.ReadLine();
                len = 0;
                str = null;
                if (mo == "0")
                  try
                  {
                        len = ClientSocket.Receive(data, 0, data.Length, SocketFlags.None);//获取服务器端数据并返回读取的字节数,会阻塞当前线程,
                                                                                        //当客户端突然掉线,往往会引发异常
                        if (data == 0)//模式0退出
                        {
                            AppendTextToTxtLog(string.Format("服务端:{0} 正常退出", ClientSocket.RemoteEndPoint.ToString()));
                            StopConnect();
                        }
                        else if (data == 1)
                        {//模式1收到了字符串
                            str = Encoding.UTF8.GetString(data, 1, len - 1);
                            AppendTextToTxtLog(string.Format("Socket信息:{0}", str));
                        }
                        //一次类推,总共有256种消息的传输模式
                  }
                  catch (Exception)
                  {
                        AppendTextToTxtLog(string.Format("服务端:{0} 非正常退出",
                            ClientSocket.RemoteEndPoint.ToString()));
                        StopConnect();
                        return;
                  }
                else if(mo == "1"){
                  SendMsg();
                }
            }
            // 也可以将第3步写入方法ReceiveData
            // Thread thread = new Thread(new ParameterizedThreadStart(ReceiveData));
            // thread.IsBackground = true;
            // thread.Start(); // 然后开启线程

      }

      private void AppendTextToTxtLog(string txt)
      {
            Console.WriteLine(txt);
      }

      private void StopConnect()
      {
            try
            {
                if (ClientSocket.Connected)
                {
                  ClientSocket.Shutdown(SocketShutdown.Both);
                  ClientSocket.Close(100);
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("或许没有成功的停止连接" + ex.ToString());
            }
      }

      public void SendMsg()
      {
            if (ClientSocket.Connected)
            {
                System.Console.WriteLine("请输入要发送信息的模式:");
                System.Console.WriteLine("0:结束");
                System.Console.WriteLine("1:字符串");
                String ms = Console.ReadLine();
                if (ms == "0") { }
                if (ms == "1")
                {
                  System.Console.WriteLine("请输入要发送的消息:");
                  String s = Console.ReadLine();
                  byte[] data = Encoding.UTF8.GetBytes(s);
                  byte[] result = new byte;//信息的二进制放在1~data.Length
                  result = 1;//第0个位置是标志位,将来我们可以用这个标志位,分辨文件类型,将来用来传文件
                  Buffer.BlockCopy(data, 0, result, 1, data.Length);//把 data从0 转 result从1 长度data.Length
                  ClientSocket.Send(result, 0, result.Length, SocketFlags.None);//发送消息
                  AppendTextToTxtLog(string.Format("本机的信息是:{0}", s));
                }
            }
      }
    }
    internal class Program
    {

      static void Main(string[] args)
      {
            System.Console.WriteLine("0:服务器端");
            System.Console.WriteLine("1:客户端");
            string ms = Console.ReadLine();
            if (ms == "0")
            {
                SocketServer server = new SocketServer();
                server.Start();
            }
            else if (ms == "1")
            {
                SocketClient client = new SocketClient();
                client.Start();
            }

      }
    }
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: C# Socket教程入门,Socket的使用方法,附可执行Demo