C#使用Socket实现局域网聊天

C#使用Socket实现局域网聊天攻略

简介

本攻略将介绍如何使用C#中的Socket类实现基于局域网的聊天功能。在该聊天室中,客户端和服务器端都需要使用Socket类来完成通信功能。在进入具体实现前,需要先说明一些基础概念和准备工作。

基础概念

  • Socket:Socket是实现网络通信的底层操作。它是位于传输层的,用于实现网络应用程序之间的双向通信。

  • IP地址:计算机在网络中的位置。IP地址由32位二进制数组成,通常用点分十进制表示。

  • 端口:是网络通信时用来识别服务的数字,通常是16位的整数。端口有两个范围:从0到1023的端口是系统用的,应用程序一般不能使用;从1024到65535的端口是留给应用程序使用。

准备工作

在开始实现聊天功能前,需要先准备好Visual Studio开发环境,选择合适的.NET框架(推荐使用.NET Framework 4.0及以上)以及安装Common.Logging库,方便后面的日志输出。

实现

服务端

在服务端,我们需要做如下操作:

  1. 创建一个Socket对象,指定地址族(AF_INET)和套接字类型(SOCK_STREAM),并绑定到本地IP地址和端口号上。
private static void StartServer()
{
    try
    {
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1234);
        Socket listener = new Socket(AddressFamily.InterNetwork,
                                     SocketType.Stream, ProtocolType.Tcp);

        listener.Bind(localEndPoint);
        listener.Listen(10);
        Console.WriteLine("Waiting for client...");

        while (true)
        {
            Socket handler = listener.Accept();
            ReceiveMessage(handler);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}
  1. 监听端口,接受客户端连接请求。

  2. 收到客户端发送的消息后,解析消息并进行回复。

private static void ReceiveMessage(Socket handler)
{
    byte[] bytes = new byte[1024];
    int bytesRec = handler.Receive(bytes);
    string data = Encoding.ASCII.GetString(bytes, 0, bytesRec);

    Console.WriteLine("Received message: {0}", data);

    byte[] msg = Encoding.ASCII.GetBytes("Server received message");
    handler.Send(msg);

    handler.Shutdown(SocketShutdown.Both);
    handler.Close();
}

以上为服务端的主要代码实现。其中,ReceiveMessage会解析客户端发送的消息并进行回复。

客户端

在客户端,我们需要做如下操作:

  1. 创建一个Socket对象,指定地址族(AF_INET)和套接字类型(SOCK_STREAM),并连接到服务端的IP地址和端口号上。
private static void StartClient()
{
    try
    {
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, 1234);

        Socket sender = new Socket(AddressFamily.InterNetwork,
                                   SocketType.Stream, ProtocolType.Tcp);

        sender.Connect(remoteEP);
        Console.WriteLine("Connected to server...");

        SendMessage(sender);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}
  1. 向服务端发送消息,并接收服务端的回复。
private static void SendMessage(Socket sender)
{
    byte[] msg = Encoding.ASCII.GetBytes("Client sending message");
    sender.Send(msg);

    byte[] bytes = new byte[1024];
    int bytesRec = sender.Receive(bytes);
    string data = Encoding.ASCII.GetString(bytes, 0, bytesRec);

    Console.WriteLine("Server reply: {0}", data);

    sender.Shutdown(SocketShutdown.Both);
    sender.Close();
}

以上为客户端的主要代码实现。SendMessage会向服务端发送消息,并接收服务端的回复。

示例1

在示例1中,我们将开启一个控制台程序作为服务端,然后开启一个或多个客户端。在控制台中输入消息,并在客户端之间进行消息的传递。示例代码如下:

服务端

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

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            StartServer();
        }

        private static void StartServer()
        {
            try
            {
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1234);
                Socket listener = new Socket(AddressFamily.InterNetwork,
                                             SocketType.Stream, ProtocolType.Tcp);

                listener.Bind(localEndPoint);
                listener.Listen(10);
                Console.WriteLine("Waiting for client...");

                while (true)
                {
                    Socket handler = listener.Accept();
                    ReceiveMessage(handler);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private static void ReceiveMessage(Socket handler)
        {
            byte[] bytes = new byte[1024];
            int bytesRec = handler.Receive(bytes);
            string data = Encoding.ASCII.GetString(bytes, 0, bytesRec);

            Console.WriteLine("Received message: {0}", data);

            byte[] msg = Encoding.ASCII.GetBytes("Server received message");
            handler.Send(msg);

            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }
    }
}

客户端

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

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            StartClient();
        }

        private static void StartClient()
        {
            try
            {
                IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, 1234);

                Socket sender = new Socket(AddressFamily.InterNetwork,
                                           SocketType.Stream, ProtocolType.Tcp);

                sender.Connect(remoteEP);
                Console.WriteLine("Connected to server...");

                SendMessage(sender);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private static void SendMessage(Socket sender)
        {
            byte[] msg = Encoding.ASCII.GetBytes("Client sending message");
            sender.Send(msg);

            byte[] bytes = new byte[1024];
            int bytesRec = sender.Receive(bytes);
            string data = Encoding.ASCII.GetString(bytes, 0, bytesRec);

            Console.WriteLine("Server reply: {0}", data);

            sender.Shutdown(SocketShutdown.Both);
            sender.Close();
        }
    }
}

示例2

在示例2中,我们将基于Window Form应用程序实现聊天功能。代码如下:

服务端

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication
{
    public partial class ServerForm : Form
    {
        private Thread listenerThread;
        private Socket listener;
        bool done = false;

        public ServerForm()
        {
            InitializeComponent();
        }

        private void Btn_Start_Click(object sender, EventArgs e)
        {
            StartServer();
        }

        private void StartServer()
        {
            try
            {
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1234);
                listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                listener.Bind(localEndPoint);
                listener.Listen(10);

                listenerThread = new Thread(ListenThread);
                listenerThread.Start();

                listBox1.Items.Add("Waiting for connection...");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ListenThread()
        {
            while (!done)
            {
                try
                {
                    Socket handler = listener.Accept();
                    ReceiveMessage(handler);
                }
                catch { }
            }
        }

        private void ReceiveMessage(Socket handler)
        {
            byte[] bytes = new byte[1024];
            int bytesRec = handler.Receive(bytes);
            string data = Encoding.ASCII.GetString(bytes, 0, bytesRec);

            listBox1.Invoke((MethodInvoker)delegate {
                listBox1.Items.Add(data);
            });

            byte[] msg = Encoding.ASCII.GetBytes("Message received on server: " + data);
            handler.Send(msg);

            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }

        private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            done = true;
            listenerThread.Abort();
            listener.Close();
        }
    }
}

客户端

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication
{
    public partial class ClientForm : Form
    {
        private Socket client;

        public ClientForm()
        {
            InitializeComponent();
        }

        private void Btn_Connect_Click(object sender, EventArgs e)
        {
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(txt_IP.Text), 1234);

            try
            {
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                client.Connect(remoteEP);
                MessageBox.Show("Connected to server...");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void Btn_Send_Click(object sender, EventArgs e)
        {
            if (client != null && client.Connected)
            {
                byte[] msg = Encoding.ASCII.GetBytes(txt_Message.Text);
                client.Send(msg);

                byte[] bytes = new byte[1024];
                int bytesRec = client.Receive(bytes);
                string data = Encoding.ASCII.GetString(bytes, 0, bytesRec);

                MessageBox.Show(data);
            }
            else
            {
                MessageBox.Show("Not connected to server...");
            }

            txt_Message.Clear();
        }

        private void ClientForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (client != null && client.Connected)
            {
                client.Shutdown(SocketShutdown.Both);
                client.Close();
            }
        }
    }
}

以上为基于Windows Form应用程序的聊天应用程序实现示例。其中,服务端代码基本与控制台程序相同,只是添加了对界面控件的调用。客户端的实现相对简单,只需完成连接和发送消息的操作。

总结

本攻略介绍了如何使用C#中的Socket类实现基于局域网的聊天功能。通过示例程序的使用,可以加深对Socket通信的理解,并掌握相关编程技能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#使用Socket实现局域网聊天 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • 详解C#中三个关键字params,Ref,out

    介绍params、ref、out这三个关键字的用法及不同之处是C#入门必备的知识。下面我们分别介绍一下这三个关键字的用法以及示例说明。 params params关键字用于表示方法传入参数的个数可能是可变的,具体用法是将类型后加上“params”关键字,如下: public void Add(params int[] numbers) { int sum =…

    C# 2023年5月31日
    00
  • Unity shader实现自由放大缩小效果

    下面是关于Unity shader实现自由放大缩小效果的完整攻略: 1. 动态修改材质的贴图坐标 首先,我们需要创建一个shader,并在shader中通过传参实现缩放。 在shader中定义一个_Scale变量,表示当前缩放的比例,代码如下: Properties { // 默认值为1 _Scale ("Scale", Range(0.…

    C# 2023年6月3日
    00
  • NetCore WebSocket即时通讯示例

    NetCore WebSocket即时通讯示例是一种使用ASP.NET Core SignalR实现WebSocket即时通讯的方法。本文将详细讲解NetCore WebSocket即时通讯示例的实现过程,包括环境搭建、代码实现、示例说明等。 环境搭建 在开始实现NetCore WebSocket即时通讯示例之前,我们需要先搭建好开发环境。具体来说,我们需要…

    C# 2023年5月16日
    00
  • C#实现操作windows系统服务(service)的方法

    C#实现操作Windows系统服务的方法,可以通过以下几个步骤来完成: 引入System.ServiceProcess命名空间 在代码文件中,使用以下代码引入System.ServiceProcess命名空间: using System.ServiceProcess; 创建服务的控制器类 public partial class Service1 : Ser…

    C# 2023年6月6日
    00
  • Unity虚拟摇杆的实现方法

    Unity虚拟摇杆的实现方法 前言 虚拟摇杆作为移动端游戏中常用的操作方式之一,其实现方法也是比较简单的。本文主要介绍基于Unity的实现方法。 实现方法 实现虚拟摇杆的主要思路是通过输入获取到用户手指在屏幕上的滑动距离,并根据这个距离计算出摇杆的偏移量,实现游戏角色的移动操作。 具体实现步骤如下: 1. 创建虚拟摇杆预制体 在Unity中创建一个UIIma…

    C# 2023年6月3日
    00
  • C# Winform文本面板带滚动条的实现过程

    下面我将为您详细讲解“C# Winform文本面板带滚动条的实现过程”。 一、需求分析 首先,我们需要明确需求,即实现一个带滚动条的文本面板,能够在添加文本时自动滚动,同时支持手动滚动。 二、实现步骤 首先,我们需要在Winform中添加一个Panel控件,并设置其AutoScroll为true,即自动显示滚动条。 然后,我们在Panel控件中添加一个Tex…

    C# 2023年5月31日
    00
  • .net自定义事件示例分享

    下面是详细的“.net自定义事件示例分享”的攻略: 1. 简介 在 .NET 中,自定义事件是一种非常常见的编程模式,该模式便于构建松耦合、可扩展和可测试的代码。在 C# 中,使用以下语法创建自定义事件: public event EventHandler<MyEventArgs> MyCustomEvent; 其中,MyCustomEvent …

    C# 2023年5月31日
    00
  • C#中一些你可能没用过的调试窗口的方法

    以下是C#中一些可能没用过的调试窗口的完整攻略。 1. 数据视图窗口 数据视图窗口用于查看和编辑调试器中的变量。在Visual Studio中打开调试器并在断点处暂停程序,可以通过选择“调试”选项卡下的“窗口”→“数据视图”打开数据视图窗口。此窗口列出当前可用的变量,允许开发人员查看和编辑这些变量的内容。另外,单击窗口顶部的“+”号,可以添加新的变量。 以下…

    C# 2023年6月6日
    00
合作推广
合作推广
分享本页
返回顶部