湖南大学计算机网络实验三:基于socket的多人聊天室程序

正文

许多计算机网络课程需要进行编写socket聊天室的课程实验,本博客提供了一个用c#编写的简易解决方案,没有图形界面。如果你的电脑上安装过.net,应该可以在一分钟之内把程序跑起来。

(代码链接在文末)

什么是Socket

简单来说Socket就是一组编程接口,方便程序员在程序中创建远程连接。本质上它是对TCP/UDP协议的封装,方便程序员编写相关内容。

使用方法

只需加入代码using System.Net.Sockets;就可以使用C#中的Socket功能了。Socket通讯的建立可以用下图简单的描述出来:

socket的信息交互


所以,编写的方法就很清晰了:首先客户端和服务端都需要新建Socket对象,用构造函数socket()去进行初始化;然后服务端需要用Socket的bind()和listen()方法监听对应端口;服务端调用accept()方法,客户端调用connect()方法,两个Socket会进行连接,随后便可以进行一系列的数据交换直至close()关闭。

代码

由于没有图形界面,代码非常简单,总共只有三个类,分别是客户端、服务端以及程序入口。我这里展示出比较重要的方法:

服务端

初始化

public Service()
{
    // 初始化socket
    socketSevice = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    // 初始化用户列表
    userList = new List<Socket>();
}

可以自己去c#的api官网查一下这些参数的含义

开始监听

public void &nbsp;Run()
{
    // 打印IP
    string AddressIP = string.Empty;
    foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
    {
        if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
        {
            AddressIP = _IPAddress.ToString();
        }
    }
    Console.WriteLine(AddressIP);
 
    // 监听指定端口
    // 这里使用IPAddress.Any是比较正确的写法,如果直接写127.0.0.1可能会导致不同设备连接出现问题
    socketSevice.Bind(new IPEndPoint(IPAddress.Any,7788));
    socketSevice.Listen(10);
    Console.WriteLine("服务器已启动");

    // 异步调用接收用户的线程
    Thread accThread = new Thread(Accept);
    accThread.IsBackground = true;
    accThread.Start();

    Console.ReadLine();
}

其实这一步骤的关键代码只有两行,也就是Bind和Listen那两行。
如果你这里写的不是IPAddress.Any,在你用两台主机测试这个程序的时候可能会遇到无数问题,不过如果你只想在一台电脑上跑,写成127.0.0.1是没有问题的。

这个方法里的最后几行是启动了一条专门等待接收用户连接的线程。关于.net的多线程写法,有兴趣的话可以持续关注我,我后面会更新相关内容的。

连接用户

// 接受用户线程
private void Accept()
{
    //接受连接
    Socket clientSocket = socketSevice.Accept();
    userList.Add(clientSocket);

    //打印对应的IP地址
    Console.WriteLine(IPToAddress(clientSocket)+"已接入聊天室"); 

    // 异步调用对应用户的接收信息线程
    Thread RecvThread = new Thread(ReceMessage);
    RecvThread.IsBackground = true;
    RecvThread.Start(clientSocket);

    // 递归调用,保证接受用户的线程一直在运行
    Accept();
}

在有用户发起连接申请之前,该线程会一直阻塞在第一行,直到连接上用户之后就会打印相关信息,激活对应这名用户的信息接收线程,并且重新启动一条本线程。

发送和接收

使用Recive()和Send()方法

客户端

连接服务端

public void Connected(string Ip,int port)
{
    clientSocket.Connect(Ip,port);
    Console.WriteLine("连接成功");

    // 异步调用接收信息的线程
    Thread RecvThread = new Thread(RecvMessage);
    RecvThread.IsBackground = true;
    RecvThread.Start();
}

非常简单。这里的IP,如果是运行在同一台电脑上的,就传入127.0.0.1就好了,如果是在两台主机上分别运行客户端和服务端,那么你需要保证这两台主机在同一局域网下,或者你把服务端运行在一台真正的服务器上。
校园网可能是不管用的,实在不行可以试一下手机的热点。
如果你想要尝试在两台主机上运行,可能遇到的问题有很多,在这里我列出几项可能的原因和解决方法:

  1. 前文中提到的要写IPAddress.Any
  2. 两台主机要处于同一局域网下。校园网可能是不行的,可以试着用手机热点。
  3. 服务端电脑的防火墙设置问题(可能会阻止外来访问),尤其主要这点如果你的客户端终端报错说:目标计算机积极拒绝……
  4. 端口被占用了(这个可能性是比较小的)

程序入口

public static void Main(String[] args) {
    Console.WriteLine("输入0以启动服务端,输入1以启动客户端");
    while(true) {
        string a=Console.ReadLine();
        int b=int.Parse(a);
        if(b==0) {
            Service service = new Service();
            service.Run();
        } else if(b==1) {
            Client client = new Client();
            client.Run();
        } else {
            Console.WriteLine("输入错误,请重新输入");
        }
    }
}

朴实无华的Main函数。这样做主要是为了方便测试,你可以直接在vsc之类的软件里面多开几个终端,然后分别运行客户端和服务端。

总结

以下贴上github链接,可以直接取用代码。

iLoner121/SocketChatRoom: 湖南大学计算机网络实验三:基于socket的多人聊天室程序 (github.com)


通过本篇博客的介绍,你应该能顺利通过学校的计算机网络课程实验(你们的计网课总不会强制要求图形界面吧?)
如果要图形界面也没关系,我打算过一段时间做几篇相关.net的图形界面制作方法,比如如何制作简单的windows窗体程序或者web程序。vs内置了丰富的框架和模板,支持用户快速的制作出一个有图形界面的程序。

文章创作不易,如果感兴趣请持续关注
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇