万金流
以码会友。 吾Q:578751655。 水平有限,轻喷,谢!
随笔 - 189,  文章 - 0,  评论 - 7,  阅读 - 14万

本例内容为书上1.4.4内容的改版,主要实现服务端和客户端分离。

使用socket:

服务端程序:

复制代码
int dataLength;
            string tmpStr;
            byte[] dataBytes1 = new byte[1024];
            //指定监听端口开始
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint myHost = new IPEndPoint(IPAddress.Any, 8080);
            //指定监听端口结束
            EndPoint client1 = new IPEndPoint(IPAddress.Any, 8080);
            socket.Bind(myHost);
            do
            {
                Console.WriteLine("等待接收...");
                dataLength = socket.ReceiveFrom(dataBytes1, ref client1);
                tmpStr = System.Text.Encoding.Unicode.GetString(dataBytes1, 0, dataLength);
                Console.WriteLine($"接收到来自{client1.ToString()}的信息:{tmpStr}");
            }while (tmpStr.ToLower() != "serverover");
            socket.Close();
            Console.WriteLine("对方已要求服务器退出,请按回车键结束。");
            Console.ReadLine();
复制代码

客户端程序:

复制代码
byte[] dataBytes;
            string tmpStr;
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            //指定使用哪个套接字发送开始
            IPEndPoint myHost = new IPEndPoint(IPAddress.Any, 8081);
            socket.Bind(myHost);
            //指定使用哪个套接字发送结束
            //指定服务器开始
            IPEndPoint remoteIPEnd = new IPEndPoint(IPAddress.Parse("192.168.1.105"), 8080);
            //指定服务器结束
            do
            {
                Console.Write("输入发送信息(exit退出):");
                tmpStr = Console.ReadLine();
                dataBytes = System.Text.Encoding.Unicode.GetBytes(tmpStr);
                socket.SendTo(dataBytes, remoteIPEnd);
            } while (tmpStr.ToLower() != "exit");
            socket.Close();
            Console.WriteLine("已经退出,请按回车键结束。");
            Console.ReadLine();
复制代码

运行效果:

 不同电脑测试也通过。

 基于此,就应当能很轻松完成P24页第4题了。


 使用udpclient:

服务端:

复制代码
static UdpClient udp;
        static void Main(string[] args)
        {
            string msg;
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9000),remote=new IPEndPoint(IPAddress.Any,0);
            udp = new UdpClient(ipep);
            do
            {
                msg = Encoding.UTF8.GetString(udp.Receive(ref remote));
                Console.WriteLine($"{remote.ToString()}:{msg}");
            }
            while (msg.ToLower() != "exit");
        }
复制代码

客户端:

复制代码
static UdpClient udp;
        static void Main(string[] args)
        {
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9100);
            udp = new UdpClient(ipep);
            udp.Connect(IPAddress.Parse("127.0.0.1"), 9000);
            string msg;
            byte[] b;
            do
            {
                msg = Console.ReadLine();
                b = Encoding.UTF8.GetBytes(msg);
                udp.Send(b, b.Length);
            } while (msg.ToLower() != "exit");
        }
复制代码

 


 

扩展:

都写到这里了,大家结合之前的网络知识,再思考一下,如何突破单边的源地址转换限制,实现内网和公网pc收发消息?

提示:内网机器先发出消息,利用出口转换表里的地址和端口对应关系,让服务器也可以访问到客户机。

代码修改1:发送消息程序,服务器ip和端口需要在运行时由用户指定。

代码修改2:内网机器的发送和接收,使用了相同的ip和端口。必须开启端口复用才能工作。代码为:“socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);”

效果如下图:

 

 其中,远程桌面使用的是一台公网机器,右侧是本机。

运行顺序为图中顺序。

此时,内网机器也能够被其他内网机器连接并接收消息:

 

这也是qq最基本的通信原理。 

思考题:如何利用一台公网服务器,构建简单聊天程序?

 

posted on   万金流  阅读(954)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

点击右上角即可分享
微信分享提示