C# Socket网络编程入门(服务器与客户端通信,客户端与客户端通信)

2 篇文章 1 订阅

WebSocket全双工通讯链接,用于前台和后台自由发送信息

一.效果展示:

效果描述:
1.服务器充当管理员,给所有人发送信息,除服务器以外其他人都能接受到。
2.其他用户发送信息除自己以外其他用户和管理员全能接受到。
在这里插入图片描述

注意:图中打码处为服务器IP和端口,每个电脑都只能访问自己的服务器以及端口,用cmd打开管理员命令窗口,用如下代码 可以查看本机所有IP和端口

netstat -a
//或者
netstat -an

在这里插入图片描述

二.服务器代码:

	public partial class MainForm : Form
{

    List<Socket> ClientProxSocketList = new List<Socket>();

    public MainForm()
    {
        InitializeComponent();
    }

    Socket proxSocket;


    //点击启动按钮
    private void btn_Start_Click(object sender, EventArgs e)
    {
        
        //1  创建Socket
        Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

        //2 绑定端口Ip
        socket.Bind(new IPEndPoint(IPAddress.Parse(txt_Ip.Text),int.Parse(txt_Port.Text)));

        //3 开启监听
        socket.Listen(1000);  //链接:最大接收请求数,超出返回错误信息

        //4 开始接收客户端的链接
        ThreadPool.QueueUserWorkItem(new WaitCallback(this.AcceptClientConnect),socket);

        
    }


    //将远程连接的客户端的IP地址和Socket存入集合中
    Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();

    public void AcceptClientConnect(object socket)
    {
        var serverSocket = socket as Socket;

        this.AppendTextToTxtLog("服务器开始接受客户端的链接。");

        while (true)
        {
            //负责跟客户通信的Socket
            proxSocket = serverSocket.Accept();
            //将远程连接的客户端的IP地址和Socket存入集合中
            dicSocket.Add(proxSocket.RemoteEndPoint.ToString(),proxSocket);
            //将远程连接的客户端IP地址和端口存储下拉框中
            //cboUsers.Items.Add(proxSocket.RemoteEndPoint.ToString());

            this.AppendTextToTxtLog(string.Format("客户端:{0}链接上了",proxSocket.RemoteEndPoint.ToString()));

            ClientProxSocketList.Add(proxSocket);

            //不停的接收当前链接的客户端发送的信息
            // proxSocket.Receive();

            ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveData),proxSocket);
        }

    }


    //接收客户端的消息
    public void ReceiveData(object socket)
    {
        var proxSocket = socket as Socket;
        byte[] data = new byte[1024 * 1024 * 2];
        while (true)
        {

            int len = 0;

            try
            {
                len = proxSocket.Receive(data, 0, data.Length, SocketFlags.None);
            }
            catch (Exception)
            {
                //异常退出
                AppendTextToTxtLog(string.Format("客户端:{0}正常退出", proxSocket.RemoteEndPoint.ToString()));
                ClientProxSocketList.Remove(proxSocket);
                return;
            }

            

            if(len <= 0)
            {
                //客户端正常退出
                AppendTextToTxtLog(string.Format("客户端:{0}正常退出", proxSocket.RemoteEndPoint.ToString()));

                ClientProxSocketList.Remove(proxSocket);
                return;//让方法结束,终结当前接受客户端数据的异步线程
            }

            //把接收到的数据放到文本框中
           string str =  Encoding.UTF8.GetString(data,0,len);
           AppendTextToTxtLog(string.Format("接收到客户端:{0}的消息是:{1}",proxSocket.RemoteEndPoint.ToString(),str));

			//服务器转发信息,除发送方以外,转发信息
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
            foreach (var item in dicSocket)
            {
                if (item.Key != proxSocket.RemoteEndPoint.ToString())
                    item.Value.Send(buffer);
            }

        }
    }

    //往日志的文本框上追加数据
    public void AppendTextToTxtLog(string txt)
    {
        if (txt_Cont.InvokeRequired)
        {
            txt_Cont.Invoke(new Action<string>(s =>
            {
                this.txt_Cont.Text = string.Format("{0}\r\n{1}", s, txt_Cont.Text);
            }),txt);
        }
        else
        {
            this.txt_Cont.Text = string.Format("{0}\r\n{1}", txt, txt_Cont.Text);
        }

        
    }


    //服务器给客户端发送信息
    private void btn_Send_Click(object sender, EventArgs e)
    {
        #region
        //foreach (var proxSocket in ClientProxSocketList)
        //{
        //    if (proxSocket.Connected)
        //    {
        //        byte[] data = Encoding.Default.GetBytes(txt_Msg.Text);
        //        proxSocket.Send(data, 0, data.Length, SocketFlags.None);
        //    }
        //}
        #endregion

        string str = txt_Msg.Text;
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
        //获取用户在下拉框中选择的IP地址
        //string ip = cboUsers.SelectedItem.ToString();





        foreach (var item in dicSocket)
        {
            //if(item.Key != proxSocket.RemoteEndPoint.ToString())
                item.Value.Send(buffer);
        }

        
        //proxSocket.Send(buffer);

    }
}

三.客户端代码:

 public partial class ClientForm : Form
{
    public ClientForm()
    {
        InitializeComponent();
    }

    Socket socketSend;

    //点击连接
    private void btn_Link_Click(object sender, EventArgs e)
    {
        //创建负责通信的Socket
        socketSend = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

        IPAddress ip = IPAddress.Parse(lab_Ip.Text);
        IPEndPoint point = new IPEndPoint(ip,Convert.ToInt32(lab_Port.Text));
        socketSend.Connect(point);

        ShowMsg("连接成功");

        //开启一个线程不停接受服务器发送来的信息
        Thread th = new Thread(Recive);
        th.IsBackground = true;
        th.Start();

    }

    //不停接受服务器发来的消息
    void Recive()
    {
        while (true)
        {
            byte[] buffer = new byte[1024 * 1024 * 3];
            //实际接受到的有效字节
            int r = socketSend.Receive(buffer);

            if(r <= 0)
            {
                break;
            }

            string s = Encoding.UTF8.GetString(buffer,0,r);

            ShowMsg(socketSend.RemoteEndPoint+":"+s);
        }
    }


    void ShowMsg(string str)
    {
        txt_Cont.AppendText(str + "\r\n");
    }

    //点击发送按钮,客户端给服务器发送消息
    private void btn_Send_Click(object sender, EventArgs e)
    {
        string str = txt_Msg.Text.Trim();
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
        socketSend.Send(buffer);
    }
}

四.总结&猜想

这里的服务器转发只用了一个Dictionary存储了所有连接服务器的Socket。如果要做一个更好的单独会话,就在数据库好友的链接表里面,记录好端口和IP,每次选择好友查询数据库,单独发送给好友

五.学习链接:

CSDN C# Socket 会话思路与实现

BiLibili Winform应用程序_多线程和socket网络编程

在这里插入图片描述

吐槽:
就很怪,现在发布文章,字数不多还提示推荐受影响。。。
CSDN路走窄了啊,浓缩的都是精华好吧。
再这样下去,我只能放弃CSDN去博客园了。

吐槽:
就很怪,现在发布文章,字数不多还提示推荐受影响。。。
CSDN路走窄了啊,浓缩的都是精华好吧。
再这样下去,我只能放弃CSDN去博客园了。

吐槽:
就很怪,现在发布文章,字数不多还提示推荐受影响。。。
CSDN路走窄了啊,浓缩的都是精华好吧。
再这样下去,我只能放弃CSDN去博客园了。

吐槽:
就很怪,现在发布文章,字数不多还提示推荐受影响。。。
CSDN路走窄了啊,浓缩的都是精华好吧。
再这样下去,我只能放弃CSDN去博客园了。

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
C#中进行socket网络编程可以实现一个服务器与多个客户端通信,以下是一个简单的示例: 服务器端代码: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; namespace Server { class Program { static void Main(string[] args) { // 创建一个TCP/IP socket对象 Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 绑定IP地址和端口号 IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 8888); listener.Bind(localEndPoint); // 开始监听连接请求 listener.Listen(10); Console.WriteLine("等待客户端连接..."); while (true) { // 接受来自客户端的连接请求 Socket handler = listener.Accept(); // 接收客户端发送的数据 byte[] buffer = new byte[1024]; int bytesRead = handler.Receive(buffer); string data = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine($"接收到客户端数据:{data}"); // 向客户端发送响应数据 byte[] responseBytes = Encoding.ASCII.GetBytes("收到你的消息了!"); handler.Send(responseBytes); // 关闭连接 handler.Shutdown(SocketShutdown.Both); handler.Close(); } } } } ``` 客户端代码: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; namespace Client { class Program { static void Main(string[] args) { // 创建一个TCP/IP socket对象 Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 连接服务器 IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint remoteEP = new IPEndPoint(ipAddress, 8888); sender.Connect(remoteEP); Console.WriteLine("连接服务器成功!"); // 向服务器发送数据 string message = "Hello, Server!"; byte[] bytes = Encoding.ASCII.GetBytes(message); sender.Send(bytes); // 接收服务器的响应数据 byte[] buffer = new byte[1024]; int bytesRead = sender.Receive(buffer); string response = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine($"接收到服务器响应:{response}"); // 关闭连接 sender.Shutdown(SocketShutdown.Both); sender.Close(); Console.ReadKey(); } } } ``` 以上代码可以实现一个简单的服务器客户端通信,如果想实现多个客户端同时连接服务器,可以使用多线程或异步编程来处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值