Socket简单通信(二)

前面已经简要介绍了一下Socket和一些相关知识,但是我想说明一点,网络通信不是只能用Socket,比如命名空间System.Net.Sockets就提供了制作Sockets网络应用程序的几个相关类,Socket类只是其一,但是个人感觉它比其他几个强大。

1.Socket类

主要用于管理连接,实现Berkeley通信端套接字接口。定义了绑定、连接网络端点及传输数据所需要的各种方法,提供处理端点连接传输等细节所需要的功能。

2.TcpListener类和TcpClient类

TcpClient类用于在同步阻止模式下通过网络来连接、发送和接受流数据。

TcpListener类用于在阻止同步模式下侦听和接受传入的连接请求。

3.UdpClient类

UdpClient类用于在阻止同步模式下通过网络来发送和接受无连接的UDP数据报。

下面就展示一下Socket简单通信的具体实现,UDP和TCP两种。

先来简单一些的UDP通信。由于这个实在是没什么太难之处就写的控制台,这个程序两端其实是一样的,UDP通信是没有客户端和服务器端之分的,分服务区端和客户端只是给两个一样的小程序编个号。(hh)

  /// <summary>
        /// 发送消息
        /// </summary>
        static void sendMsg()
        {
            EndPoint point = new IPEndPoint(IPAddress.Parse("192.168.0.104"), 9500);
            while (true)
            {
                string msg = Console.ReadLine();
                client.SendTo(Encoding.UTF8.GetBytes(msg), point);
            }
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        static void ReciveMsg()
        {
            while (true)
            {
                EndPoint point = new IPEndPoint(IPAddress.Any, 0);   //用来保存对方的ip和端口号
                byte[] buffer = new byte[1024];
                int length = client.ReceiveFrom(buffer, ref point);    //接收数据报
                string message = Encoding.UTF8.GetString(buffer, 0, length);
                Console.WriteLine(point.ToString()+":" + message);
            }
        }

这是接受和发送数据报的两个函数。

 public static Socket client;
        static void Main(string[] args)
        {
            client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            client.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.104"), 10050));
            Console.WriteLine("---------客户端已开启------");
            Thread t = new Thread(sendMsg);
            t.Start();
            Thread t2 = new Thread(ReciveMsg);
            t2.Start();
            t2.IsBackground = true;
           
        }

然后就直接在主函数里创建两个线程,一个Socket,开始等待接收消息和发送消息。

服务器端和这个一模一样,我就不贴了。这个其实就是局域网聊天小程序
知道对方的端口和IP,在一个局域网内就可以通信了,端口一般取1024以上的,自己也可以慢慢试。

————————————————————————————————
可以看出,UDP通信只需要一个Socket就可以实现通信了,这种方式不关心对方是否在线,就像发邮件一样,知道你是谁,你的邮箱地址是什么(IP和端口),然后我就直接发过去,效率高,但是会可能会丢失数据,因此视频什么的就可以用这种方式传输,毕竟丢失一些数据我们又怎么可能看出来呢。

效果图:

在这里插入图片描述
在这里插入图片描述
—————————————————————————————————

再来看看TCP通信的。

首先服务器端必须要有一个监听Socket,监听是否有客户端的连接请求。

   /// <summary>
        /// 服务端开始监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_Listening_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = GetLocalIP();              //自动获取IP
            IPAddress ip = IPAddress.Parse(textBox1.Text);  //服务端IP地址
            IPEndPoint point = new IPEndPoint(ip, int.Parse(textBox2.Text));   //IP和端口号
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);   //创建监听用的Socket
            try
            {
                socket.Bind(point);   //socket监听主机上指定端口并绑定
                socket.Listen(5);     //可允许队列最多5个客户端
                ShowMessage("服务器开始监听");
                Thread thread = new Thread(AcceptInformation);
                thread.IsBackground = true;
                thread.Start(socket);
            }
            catch (Exception ex)
            {
                ShowMessage(ex.Message);
            }

如果监听到请求就接收请求并再创建一个Socket用来通信。

        /// <summary>
        /// 接收客户端请求信息
        /// </summary>
        /// <param name="sender"></param>
        public void AcceptInformation(object sender)
        {
            Socket socket = sender as Socket;
            while (true)
            {
                try
                {
                    Socket socket1 = socket.Accept();  //创建通信用的socket
                    string point = socket1.RemoteEndPoint.ToString();  //获取端口结点
                    ShowMessage(point + "连接成功");
                    listBox1.Items.Clear();
                    listBox1.Items.Add(point);
                    dictory.Add(point, socket1);                    
                    Thread accept = new Thread(ReceiveMessage);      //接受消息
                    accept.IsBackground = true;
                    accept.Start(socket1);
                }
                catch (Exception ex)
                {
                    ShowMessage(ex.Message);
                }
            }
        }

然后就是发送消息与接受消息的实现了。

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                ShowMessage(GetLocalIP().ToString ()+":"+txtMsg.Text);   //服务端显示消息
                string point = listBox1.Text;  //之前存储的IP
                byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
                dictory[point].Send(buffer);         //发送消息  注:用之前集合中存储的键值,也就是端口是键,socket是值     

            }
            catch (Exception ex)
            {
                ShowMessage(ex.Message);
            }
        }
        /// <summary>
        /// 接受消息
        /// </summary>
        /// <param name="sender"></param>
        public void ReceiveMessage(object sender)
        {
            Socket client = sender as Socket;
            while (true)
            {
                try
                {
                    byte[] Byte = new byte[1024 * 1024];  //定义数组用来存放从客户端接受到的数据(大小为1M)
                    int Mid = client.Receive(Byte);    //将接受过来的数据存放到Byte中,并得到接受数据的长度
                    string str = Encoding.UTF8.GetString(Byte, 0, Mid);  //将字节转换成字符串
                    ShowMessage(client.RemoteEndPoint.ToString() + ":" + str);
                }
                catch (Exception ex)
                {
                    ShowMessage(ex.Message);
                }
            }
        }

额,为了省事,我还写了一个获取本地IP的函数

 /// <summary>
        /// 获取本地IP
        /// </summary>
        /// <returns></returns>
        public string GetLocalIP() 
        {
            try
            {
                string HostName = Dns.GetHostName();
                IPHostEntry hostEntry = Dns.GetHostEntry(HostName);
                for (int j = 0; j < hostEntry.AddressList.Length; j++) 
                {
                    if(hostEntry .AddressList [j].AddressFamily ==AddressFamily.InterNetwork )
                    return hostEntry.AddressList[j].ToString();
                }
                return "Error";
            }
            catch (Exception ex) 
            {
                ShowMessage("获取本机IP失败!"+ex.Message);
                return "Error";
            }
        }

客户端更简单就不贴了。(所有源码我就放在文末,有需要者自取吧)
————————————————————————————————
通过TCP通信的例子可以发现它至少需要两个Socket,一个用来监听,一个用来通信,监听是为了两方能够成功连接,这就是比UDP安全的地方,也是速度更慢的地方。

放一下效果图吧

在这里插入图片描述
在这里插入图片描述
需要注意一下,服务器端发消息时要选中一个客户端,否则就会出现图中那种错误“未包含在字典中”。

这个程序还有很多不足之处,但是仅仅当作学习的例子吧,在一方退出时会
一直抽风,应该会干扰其他的客户端(我还没测过)。除此之外,Socket通信还可以传图片,传文件,放广播等(具体的还在研究中,搞出来了可以分享给大家)。我写这个仅仅用于学习,有些代码肯定也是借鉴了其他人的,今后有时间再改进了。。。。。

—————————————————————————————————

TCP聊天demo

UDP聊天demo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值