我想实现一个类似QQ的即时通讯,并不需要那么复杂,谁作过类似这样的东西,可不可以让我也学习一下,我见网上也有好多,只是有些源码是杂乱的,我不明白一些内容所以也看不懂,谁能提供一个吗,多谢

解决方案 »

  1.   

    http://www.codeproject.com/csharp/ipchat.asp
      

  2.   

    3.服务器端程序的代码编写。 对于服务器端,主要的作用是监听客户端的连接请求并确认其请求。程序一开始便打开一个StartListening()线程。 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() ); } } } 该线程是一直处于运行状态的。当服务器端接收到一个来自客户端的连接请求后,它就打开一个ServiceClient()线程来服务客户端。当一个连接被建立后,每个客户端就被赋予一个属于它自己的套接字。同时,一个Client类的对象被建立。该对象包含了客户端的一些相关信息,该信息被保存在一个数组列表中。Client类如下(也可参见源代码中的Client.cs文件): using System; using System.Threading; namespace ChatServer { using System.Net.Sockets; using System.Net; /// /// Client 的摘要说明。 /// public class Client { private Thread clthread; private EndPoint endpoint; private string name; private Socket sock; public Client(string _name, EndPoint _endpoint, Thread _thread, Socket _sock) { // TODO: 在此处添加构造函数逻辑 clthread = _thread; endpoint = _endpoint; name = _name; sock = _sock; } public override string ToString() { return endpoint.ToString()+ " : " + name; } public Thread CLThread { get{return clthread;} set{clthread = value;} } public EndPoint Host { get{return endpoint;} set{endpoint = value;} } public string Name { get{return name;} set{name = value;} } public Socket Sock { get{return sock;} set{sock = value;} } } } 程序的主体部分应是ServiceClient()函数。该函数是一个独立的线程,其主要部分是一个while循环。在循环体内,程序处理各种客户端命令。服务器端接收来自客户端的以ASCII码给出的字符串,其中包含了一个“|”形式的分隔符。字符串中“|”以前的部分就是具体的命令,包括CONN、CHAT、PRIV、GONE四种类型。CONN命令建立一个新的客户端连接,将现有的用户列表发送给新用户并告知其他用户有一个新用户加入。CHAT命令将新的信息发送给所有用户。PRIV命令将悄悄话发送给某个用户。GONE命令从用户列表中除去一个已离开的用户并告知其他的用户某某已经离开了。同时,GONE命令可以设置布尔型的变量keepalive为false从而结束与客户端连接的线程。ServiceClient()函数如下: private void ServiceClient() { Socket client = clientsocket; bool keepalive = true; while (keepalive) { Byte[] buffer = new Byte[1024]; client.Receive(buffer); string clientcommand = System.Text.Encoding.ASCII.GetString(buffer); string[] tokens = clientcommand.Split(new Char[]{'|'}); Console.WriteLine(clientcommand); if (tokens[0] == "CONN") { for(int n=0; n< 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 = "LIST|" + GetChatterList() +"\r\n"; SendToClient(c, message); lbClients.Items.Add(c); } if (tokens[0] == "CHAT") { for(int n=0; n< n++)> { Client cl = (Client)clients[n]; SendToClient(cl, clientcommand); } } if (tokens[0] == "PRIV") { string destclient = tokens[3]; for(int n=0; n< 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] == "GONE") { int remove = 0; bool found = false; int c = clients.Count; for(int n=0; n< n++)> { Client cl = (Client)clients[n]; SendToClient(cl, clientcommand); if(cl.Name.CompareTo(tokens[1]) == 0) { remove = n; found = true; lbClients.Items.Remove(cl); } } if(found) clients.RemoveAt(remove); client.Close(); keepalive = false; } } } 这样,服务器端程序就基本完成了。(其他略次要的代码可以参见源代码中的Form1.cs文件)程序运行图示如下: 
      

  3.   

    客户端程序: 1.打开VS.net,新建一个C#的模板为“Windows 应用程序”的项目,不妨命名为“ChatClient”。 2.布置界面。往界面上添加一个ListBox控件(用于显示用户列表),一个RichTextBox控件(用于显示聊天消息以及系统消息),一个TextBox控件(用于发送消息),一个CheckBox控件(确定是否为悄悄话),一个StatusBar控件以及四个Button控件(分别为“连接”、“断开连接”、“开始记录”、“发送”)。各个控件的属性设置可以参见源代码中的具体设置,这里从略。界面设计好后的图象如下: 3.客户端程序的代码编写。 当客户端试图和服务器端进行连接时,一个连接必须建立而且得向服务器端进行注册。EstablishConnection()函数运用一个TcpClient来和服务器端取得连接,同时创建一个NetworkStream来发送消息。还有,端口号和服务器端的是保持一致的,均为5555。EstablishConnection()函数如下: private void EstablishConnection() { statusBar1.Text = "正在连接到服务器"; try { clientsocket = new TcpClient(serveraddress,serverport); ns = clientsocket.GetStream(); sr = new StreamReader(ns); connected = true; } catch (Exception) { MessageBox.Show("不能连接到服务器!","错误", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); statusBar1.Text = "已断开连接"; } } 在和服务器端连接成功后,程序就用RegisterWithServer()函数向服务器端发送一个CONN命令。该命令先是发送该用户的名称,然后从服务器端获得其他所有用户的列表,所有用户列表是在ListBox控件中显示的。该函数如下: private void RegisterWithServer() { try { string command = "CONN|" + ChatOut.Text; Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray()); ns.Write(outbytes,0,outbytes.Length); string serverresponse = sr.ReadLine(); serverresponse.Trim(); string[] tokens = serverresponse.Split(new Char[]{'|'}); if(tokens[0] == "LIST") { statusBar1.Text = "已连接"; btnDisconnect.Enabled = true; } for(int n=1; n< n++)> lbChatters.Items.Add(tokens[n].Trim(new char[]{'\r','\n'})); this.Text = clientname + ":已连接到服务器"; } catch (Exception) { MessageBox.Show("注册时发生错误!","错误", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } 在此之后,当然就是用户之间的聊天了,由ReceiveChat()函数来完成。该函数是一个独立的线程,它处理所有用户获得的消息和用户发送的消息。它主要处理了CHAT、PRIV、JOIN、GONE、QUIT等命令,处理的方法和服务器端的类似。具体函数实现如下: private void ReceiveChat() { bool keepalive = true; while (keepalive) { try { Byte[] buffer = new Byte[2048]; ns.Read(buffer,0,buffer.Length); string chatter = System.Text.Encoding.ASCII.GetString(buffer); string[] tokens = chatter.Split(new Char[]{'|'}); if (tokens[0] == "CHAT") { rtbChatIn.AppendText(tokens[1]); if(logging) logwriter.WriteLine(tokens[1]); } if (tokens[0] == "PRIV") { rtbChatIn.AppendText("Private from "); rtbChatIn.AppendText(tokens[1].Trim() ); rtbChatIn.AppendText(tokens[2] + "\r\n"); if(logging) { logwriter.Write("Private from "); logwriter.Write(tokens[1].Trim() ); logwriter.WriteLine(tokens[2] + "\r\n"); } } if (tokens[0] == "JOIN") { rtbChatIn.AppendText(tokens[1].Trim() ); rtbChatIn.AppendText(" has joined the Chat\r\n"); if(logging) { logwriter.WriteLine(tokens[1]+" has joined the Chat"); } string newguy = tokens[1].Trim(new char[]{'\r','\n'}); lbChatters.Items.Add(newguy); } if (tokens[0] == "GONE") { rtbChatIn.AppendText(tokens[1].Trim() ); rtbChatIn.AppendText(" has left the Chat\r\n"); if(logging) { logwriter.WriteLine(tokens[1]+" has left the Chat"); } lbChatters.Items.Remove(tokens[1].Trim(new char[]{'\r','\n'})); } if (tokens[0] == "QUIT") { ns.Close(); clientsocket.Close(); keepalive = false; statusBar1.Text = "服务器端已停止"; connected= false; btnSend.Enabled = false; btnDisconnect.Enabled = false; } } catch(Exception){} } } 通过以上的一些函数,客户端程序之间就可以进行自由地聊天了,各个用户之间还可以互相发送悄悄话。所以程序已经实现了聊天室的基本功能了,不过最后各个用户还要正常地退出,那就要用到QuitChat()函数了。该函数的具体实现如下: private void QuitChat() { if(connected) { try { string command = "GONE|" + clientname; Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray()); ns.Write(outbytes,0,outbytes.Length); clientsocket.Close(); } catch(Exception) { } } if(logging) logwriter.Close(); if(receive != null && receive.IsAlive) receive.Abort(); this.Text = "客户端"; } 
      

  4.   

    呵呵,楼主其实可以了解一下jabber的
      

  5.   

    你先了解一下tcp/ip协议,否则很多东西都是一知半解,难以写出好程序。QQ这样的东西架构是比较复杂的,外部网络的消息能穿透防火墙达到内网,这就是需要考虑不少问题的。
      

  6.   

    yh95 可不可以把你源文件给我啊,我看你写了那么多,应该差不多源文件也就是那么多了,你都给我我试试行吗
    copico告诉的网址我看了,我也下载了,还是有些弄不了,全是英文,我太笨