多人聊天室程序(P2P)C#版

P2P系统功能描述

Ø         登陆验证功能:对于账号填写错误等,需提示给用户;

Ø         客户通过服务器转发,实现私聊和群聊模式;

Ø         客户间可以发送数据消息,也可传送文件数据;

Ø         聊天时可以插入图片等多媒体信息;

Ø         显示目前其他用户列表,能够提示在线用户数目、状态等;

Ø         具有保存和清空聊天记录的功能;

Ø         具有友好、易用、美观的图形界面,并且无垃圾信息。

 

协议结构

Ø         通信协议(数据包分析)

接受到一个完整的数据包后,就对其进行分析,取出数据包类型,然后根据不同的类型进行处理。

Ø         数据包格式:消息头|消息内容

消息头说明:

            CONNECT:建立连接的数据

            PRIV:表示私聊模式

            CHAT:表示群聊模式

            LEAVE:表示某个客户程序关闭了与服务器的连接

            LISTEN:表示监听客户的服务请求

            JOIN:表示某个客户程序加入了聊天室

            QUIT:表示服务器退出 

消息内容说明:

            在建立连接的数据包中,消息内容只包括自己的用户名;

            在私聊模式下,消息内容包括自己的用户名、数据和指定的私聊用户名;

            在群聊模式下,消息内容包括自己的用户名和数据;

            LISTEN模式下,消息内容只包括用户名;

 

 

 

 

 

客户端代码:

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; namespace 聊天室程序 { public partial class chatface : Form { private int serverport; private TcpClient clientsocket; private NetworkStream ns; private StreamReader sr; private Thread recThread=null; private string serveraddress; private string clientname; private bool connected = false; public chatface() { InitializeComponent(); btn_savemessage.Enabled = false; btn_shutdown.Enabled = false; btn_stopconnect.Enabled = false; btn_send.Enabled = false; radioBtn_public.Checked = true; textBox_port.Text = "2500"; textBox_ip.Text = "127.0.0.1"; } protected override void OnClosed(EventArgs e) { QuitChat(); if (recThread != null && recThread.IsAlive) recThread.Abort(); base.OnClosed(e); } private void CreateConnection() { label_show.Text="连接到服务器"; try { clientsocket = new TcpClient(serveraddress, serverport); ns = clientsocket.GetStream(); sr = new StreamReader(ns); connected = true; } catch (Exception e) { MessageBox.Show("无法连接到服务器", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); label_show.Text = "未连接到服务器"; } } private void StoreforServer() { try { string command = "CONNECT|" + textBox_username.Text; Byte[] outbytes = System.Text.Encoding.Default.GetBytes(command); ns.Write(outbytes,0,outbytes.Length); string serverresponse = sr.ReadLine(); serverresponse.Trim(); string[] tokens = serverresponse.Split(new Char[]{'|'}); if(tokens[0] == "LISTEN") { label_show.Text = "连接到服务器"; btn_stopconnect.Enabled = true; } for(int n=1; n

 

 

服务器端代码:

using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.Threading; namespace 聊天室服务器端 { public partial class Form1 : Form { private int listenport=2500; //服务器端监听端口 private TcpListener listener; //服务器监听器 private ArrayList clients; // 已连接客户端数组 private Thread processor; //主线程 private Socket clientsocket; //客户端套接字 private Thread clientservice; //客户端线程 public Form1() { InitializeComponent(); clients = new ArrayList(); //开始一个监听线程 processor = new Thread(new ThreadStart(StartListening)); processor.Start(); } protected override void OnClosed(EventArgs e)//关闭时清除所有线程 { try { for (int n = 0; n < clients.Count; n++) { Client cl = (Client)clients[n]; SendToClient(cl, "QUIT|"); cl.Sock.Close(); cl.Client_Thread.Abort(); } listener.Stop(); if (processor != null) processor.Abort(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } base.OnClosed(e); } private void StartListening() { listener = new TcpListener(listenport); listener.Start(); while (true) { try { Socket s = listener.AcceptSocket(); clientsocket = s; clientservice = new Thread(new ThreadStart(ServiceClient)); clientservice.Start(); //开始监听 } catch (Exception e) { Console.WriteLine(e.ToString()); } } //listener.Stop(); } private void ServiceClient() { Socket client = clientsocket; bool alive = true; while (alive) { Byte[] buffer = new Byte[2048000]; client.Receive(buffer); // string time = System.DateTime.Now.ToString(); string clientcommand = System.Text.Encoding.Default.GetString(buffer); string[] tokens = clientcommand.Split(new Char[] { '|' }); if (tokens[0] == "CONNECT") { for (int n = 0; n < clients.Count; n++) { Client cl = (Client)clients[n]; SendToClient(cl, "JOIN|" + tokens[1]); } EndPoint ep = client.RemoteEndPoint; Client c = new Client(tokens[1], ep, clientservice, client); clients.Add(c); string message = "LISTEN|" + GetChatterList() + "/r/n"; SendToClient(c, message); clientlist.Items.Add(c); } if (tokens[0] == "CHAT") { for (int n = 0; n < clients.Count; n++) { Client cl = (Client)clients[n]; SendToClient(cl, clientcommand); } } if (tokens[0] == "PRIV") { string destclient = tokens[3]; for (int n = 0; n < clients.Count; n++) { Client cl = (Client)clients[n]; if (cl.Name.CompareTo(tokens[3]) == 0) SendToClient(cl, clientcommand); if (cl.Name.CompareTo(tokens[1]) == 0) SendToClient(cl, clientcommand); } } if (tokens[0] == "LEAVE") { int remove = 0; bool found = false; int c = clients.Count; for (int n = 0; n < c; n++) { Client cl = (Client)clients[n]; SendToClient(cl, clientcommand); if (cl.Name.CompareTo(tokens[1]) == 0) { remove = n; found = true; clientlist.Items.Remove(cl); } } if (found) clients.RemoveAt(remove); client.Close(); alive = false; } } } private void SendToClient(Client cl, string message) { try { byte[] buffer = System.Text.Encoding.Default.GetBytes(message.ToCharArray()); cl.Sock.Send(buffer, buffer.Length, 0); } catch (Exception e) { cl.Sock.Close(); cl.Client_Thread.Abort(); clients.Remove(cl); clientlist.Items.Remove(cl.Name + " : " + cl.Host.ToString()); } } private string GetChatterList() { string chatters = ""; for (int n = 0; n < clients.Count; n++) { Client cl = (Client)clients[n]; chatters += cl.Name; chatters += "|"; } chatters.Trim(new char[] { '|' }); return chatters; } } }

 

 

 

 

截图:

 

 

 

你可能感兴趣的:(编程之美)