云计算百科
云计算领域专业知识百科平台

C# Socket服务器与客户端

Socket通信

效果展示

​​

QQ20241112-114846

Socket的基本概念

Socket:它是网络通信的一个接口,代表了通信的一个端点。可以想象成一条虚拟的电话线,一端连接客户端,另一端连接服务器。

协议:Socket可以基于多种协议进行通信,最常用的是TCP(传输控制协议)和UDP(用户数据报协议)。TCP是面向连接、可靠的协议,而UDP是无连接、快速的协议。

Socket通信的基本流程

服务端:

  • 创建Socket对象:使用socket()函数创建套接字。

  • 绑定IP地址和端口号:使用bind()函数将Socket绑定到指定的IP和端口。

  • 监听连接:使用listen()函数将Socket设置为监听状态,等待客户端连接。

  • 接收连接请求:使用accept()函数接收客户端的连接请求,返回一个新的Socket实例,用于与客户端通信。

  • 处理数据通信:服务端和客户端通过send()和recv()函数进行数据交换。

  • 关闭连接:通信结束后,使用close()函数关闭Socket。

  • 客户端:

  • 创建Socket对象:客户端使用socket()函数创建套接字。

  • 连接服务器:使用connect()函数连接到服务器的IP地址和端口。

  • 数据通信:客户端与服务端通过send()和recv()函数交换数据。

  • 关闭连接:通信结束后关闭Socket。

  • 示例代码

    Server服务器

    窗体展示

    查询本机IP地址

    private void GetIp()//获取本机ip { string hostName = Dns.GetHostName(); // 获取本机名称 IPAddress[] ipList = Dns.GetHostAddresses(hostName);//本机ip(包括ipv4和ipv6)

    foreach (IPAddress ip in ipList)       // foreach不需要手动管理索引
    {
        uiComboBox_IP.Items.Add(ip.ToString().Trim());
        // .Trim():去除转换后的字符串首尾的空白字符
        // (虽然通常 IP 地址字符串没有空格,这里用 .Trim() 只是更保险的做法)。
    }

    // 查询IPV4,将查询到的第一个IP存放在文本框中
    int index = 0;
    foreach (IPAddress ip in ipList)
    {
        if (ip.AddressFamily == AddressFamily.InterNetwork)
        {
            break;
            // 查询到第一个后就 停止
        }
        index++;
    }
    uiComboBox_IP.SelectedIndex = index;
    uiTextBox_Port.Text = "8081";
    }

    创建Socket()服务器

    /// <summary>
    /// 客户端的Socket
    /// </summary>
    private Socket clientSocket;
    // 存储5M大小的数据
    byte[] buffer = new byte[1024 * 1024 * 5];
    private void btn_StartListen_Click(object sender, EventArgs e)
    {
    //AddressFamily–地址类型
    //AddressFamily.InterNetwork–>IPV4
    //SocketType.Stream–>以字节流的方式传输
    //ProtocolType.Tcp–>传输协议;

    // 1.创建服务器Socket()
    Socket socket =new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    // 2.绑定IP和端口Bind()
    IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(uiComboBox_IP.SelectedItem.ToString()), int.Parse(uiTextBox_Port.Text));
    socket.Bind(endPoint);

    PrintfLog("绑定端口和IP成功");

    Console.WriteLine();

    // 3.监听连接Listen()
    socket.Listen(10);

    // 接收连接请求 Accept()
    // Task.Run会在线程池中启动一个新任务
    Task<bool> task = Task.Run(() =>
    {
        while (true)
        {
            //等待客户端建立连接
            clientSocket=socket.Accept();
            PrintfLog("服务器与客户端连接成功");
            return true;
        }
    });
    var awaiter= task.GetAwaiter();
    awaiter.OnCompleted(() =>
    {
        Task.Run(() =>
        {
            while (true)
            {
                clientSocket.Receive(buffer);
                if (buffer.Length == 0)
                {
                    break;
                }
                string str = Encoding.UTF8.GetString(buffer,0, buffer.Length);
                PrintfLog("接受数据:"+str);
             
            }
        });
    });
    }

    文本显示框

    void PrintfLog(string str)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(() =>
            {
                // "F" 是标准的日期和时间格式字符串
                textBox_Log.AppendText(DateTime.Now.ToString("F") + str + "\\r\\n");
            }));
        }
        else
        {
            textBox_Log.AppendText(DateTime.Now.ToString("F") + str + "\\r\\n");
        }
    }

    输入栏

    private void btn_Send_Click(object sender, EventArgs e) { string str = textBox2.Text;

    byte [] buffer=Encoding.UTF8.GetBytes(str);

    clientSocket.Send(buffer,buffer.Length,0);

    textBox2.Clear();

    textBox_Log.AppendText(DateTime.Now.ToString("F") + "发送数据>:" + str + "\\r\\n");
    }

    关闭

    private void button1_Click(object sender, EventArgs e)
    {
    this.Close();
    }

    小建议 

    可以把获取本机IP的函数放在Form1 构造函数中是为了在窗体启动时自动获取并显示本机的IP地址列表,以便用户可以直接选择一个IP地址,无需手动输入。

    Client客户端

    窗体展示

    connect()连接

    private Socket soketSend;
    byte[] buff = new byte[1024 * 1024 * 5];
    Thread thread;
    private void button1_Click(object sender, EventArgs e) {
    //AddressFamily–地址类型
    //AddressFamily.InterNetwork–>IPV4
    //SocketType.Stream–>以字节流的方式传输
    //ProtocolType.Tcp–>传输协议;
    soketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    //绑定端口和IP
    IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));

    soketSend.Connect(endPoint);

    textBox_log.AppendText("客户端连接服务器成功" + "\\r\\n");

    thread = new Thread(() =>
    {
        while (true)
        {
            //Receive是有效数据得长度
            int len = soketSend.Receive(buff);
            if (len == 0)
            {
                break;
            }
            string str = Encoding.UTF8.GetString(buff, 0, len);

            this.Invoke(new Action(() =>
            {
                textBox_log.AppendText(DateTime.Now.ToString("F") + "接受服务器消息:" + str + "\\r\\n");
            }));

        }
    });
    thread.Start();
    }

    发送消息send()

    private void button2_Click(object sender, EventArgs e)
    {
    string str = textBox4.Text;
    byte[] bytes= Encoding.UTF8.GetBytes(str);
    soketSend.Send(bytes); textBox4.Clear();
    textBox_log.AppendText(DateTime.Now.ToString("F") + "发送服务器消息:" + str + "\\r\\n");
    }

    关闭

    private void close_Click(object sender, EventArgs e)
    {
    this.Close();
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » C# Socket服务器与客户端
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!