C# socket tcp 通讯的实现(0基础)

原理

        远程服务器运行服务器程序,建立起socket服务器,不断监听某端口,当有信息传递过来时,对该信息进行处理,并给信息来源反馈处理结果。

        本地客户端建立器socket连接,连接上服务器后,可以向对方发送和接收消息。

        总而言之,socket通讯仅仅是本地客户端和远程服务器进行信息交互的“电话协议”,客户端和服务器就是两台“电话”,这一点无论tcp通讯抑或是udp通讯皆是如此。

架构

        本文采用【控制台应用程序】的形式来表述,去除了桌面程序很多无必要代码生成的干扰,方便大家直接学习核心的部分。

服务器socket搭建流程。

        1.创建socket实例(选择ipv4协议,流形式,tcp协议作为其参数,因为这篇博客分享的是tcp通讯的实现)

        2.绑定指定ip地址和端口号(本文示例ip=127.0.0.1,port=8808,个人比较迷信,喜欢喜庆一点的数字)

        3.开启监听队列,设置好监听队列的最多数目,如果同时被太多客户端连接的话,我们可怜的内存和CPU可能处理不过来,设置队列的目的是让超过指定数目的客户端连接先排好队,再依次处理,这个排队的细节不需要我们处理,大佬底层里已经封装好(本文设置队列为8)

        4.开启新线程接收客户端连接(由于同一时间可能不同的客户端对服务器发起连接请求,所以我们需要利用多线程技术)

        5.在每个客户端连接后,我们对其开启接收信息线程(tcp是可靠连接,连接上之后,直到连接断开之前,双方都可以互相发送消息,直至某一方主动关闭)

客户端socket搭建流程

        1.创建socket实例(选择ipv4协议,流形式,tcp协议作为其参数,因为这篇博客分享的是tcp通讯的实现)

        2.连接上述ip地址和端口号(本文示例ip=127.0.0.1,port=8808,个人比较迷信,喜欢喜庆一点的数字)

        3.开启发送消息线程

        4.开启接收消息线程

代码(服务端)

class Program
    {
        static Socket server;

        static readonly Dictionary<string, Socket> clients = new Dictionary<string, Socket>();

        static void Main()
        {

            CreateServer();

            new Thread(() =>
             {
                 try
                 {
                     Accept(server);
                 }
                 catch (Exception e)
                 {
                     Console.WriteLine(e.Message);
                 }
             }).Start();
        }

        static void CreateServer()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress iPAddress = new IPAddress(new byte[] { 127, 0, 0, 1 });
            int port = 8088;
            EndPoint endPoint = new IPEndPoint(iPAddress, port);
            server.Bind(endPoint);
            server.Listen(8);

            Console.WriteLine("tcp端口已经打开,127.0.0.1:8088");
            DisplayAllClients();

        }

        static void Accept(Object obj)
        {
            Socket socket = (Socket)obj;
            while (true)
            {
                Socket client = socket.Accept();
                string ip = client.RemoteEndPoint.ToString();
                if (!clients.ContainsKey(ip))
                {
                    clients.Add(ip, client);
                    Console.WriteLine(ip + "已连接");
                    DisplayAllClients();
                }

                new Thread(() =>
                {
                    try
                    {
                        Recieve(client);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        clients.Remove(ip);
                    }
                })
                { IsBackground = true }.Start();
            }
        }

        static void Recieve(Object obj)
        {
            Socket client = (Socket)obj;
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 8];
                    int length = client.Receive(buffer);

                    string message = Encoding.Default.GetString(buffer, 0, length);

                    if (message == null || message.Length == 0 || message == "close")
                    {
                        string ip = client.RemoteEndPoint.ToString();
                        Console.WriteLine(ip + "连接断开!");
                        clients.Remove(ip);
                        DisplayAllClients();
                        break;
                    }

                    Console.WriteLine(client.RemoteEndPoint.ToString() + ":" + message);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    clients.Remove(client.RemoteEndPoint.ToString());
                    DisplayAllClients();
                    break;
                }
            }
        }

        static void DisplayAllClients()
        {
            if (clients.Values.Count == 0)
            {
                Console.WriteLine("目前无连接");
                Console.WriteLine("等待新的连接");
            }
            else
            {
                Console.WriteLine("目前所有连接");
                Console.WriteLine("+==========+");
                foreach (Socket client in clients.Values)
                {
                    Console.WriteLine(client.RemoteEndPoint.ToString());
                }
                Console.WriteLine("+==========+");
                Console.WriteLine();
            }
        }
    }

别忘了引用名命空间

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;        

代码(客户端)

class Program
    {
        static Socket client;

        static void Main(string[] args)
        {
            CreateClient();

            new Thread(() =>
            {
                Thread.Sleep(500);
                SendMessage();
            }).Start();

            new Thread(() =>
            {
                Thread.Sleep(500);
                ReceiveMessage();
            }).Start();

        }

        static void CreateClient()
        {
            try
            {
                IPAddress iPAdress = new IPAddress(new byte[] { 127, 0, 0, 1 });
                int port = 8088;
                IPEndPoint iPEndPoint = new IPEndPoint(iPAdress, port);
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                client.Connect(iPEndPoint);
                Console.WriteLine("已经连接上服务器");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.ReadKey();
                Process.GetCurrentProcess().Close();
            }
        }

        static void SendMessage()
        {
            try
            {
                while (true)
                {
                    Console.WriteLine("等待发送信息,回车->发送,close->断开连接");
                    string s = Console.ReadLine();
                    client.Send(Encoding.Default.GetBytes(s));
                    Console.WriteLine("发送成功!\n");

                    if (s == "close")
                    {
                        client.Close();
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        static void ReceiveMessage()
        {
            try
            {
                while (true)
                {
                    byte[] buffer = new byte[1024 * 1024 * 8];
                    int length = client.Receive(buffer);
                    string msg = Encoding.Default.GetString(buffer, 0, length);
                    if (buffer.Length > 0)
                    {
                        Console.WriteLine("服务器:" + msg);
                    }
                    else
                    {
                        Console.WriteLine("断开连接");
                        break;
                    }
                    Thread.Sleep(100);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

 同样别忘了名命空间

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

测试

        1.创建完成两个项目并分别复制代码进去后,引入名命空间去除编译报错,分别生成解决方案。

        2.分别找到两个exe可执行文件,先开启服务器程序,再开启客户端程序。

        3.客户端主动向服务器发送消息

        4.客户端主动关闭连接

总结

        socket通讯在信息交互中占据非常重要的地位,我们学习C#这一门语言需要对这个知识点重点掌握,必须能够自己手撕socket通讯服务器和客户端的基本架构代码,这对个人理解多线程这一块内容也是非常有帮助的。

        以上的介绍如果你都认真参考并自己动手参与代码编写,你就会发现我根本就没说得很详细。没错,我是故意的!

        发现问题先自己优先思考,有问题欢迎加扣提出(17359 40176 冰凌),事先声明,免费答疑。如果你只是单纯来上课的,我可是会厚着脸皮要饭的哦。

 

  • 1
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值