国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

java實現(xiàn)qq聊天(超詳細)

這篇具有很好參考價值的文章主要介紹了java實現(xiàn)qq聊天(超詳細)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

java語言實踐課內容:聊天室小程序或QQ

功能要求:
聊天室:使用圖形用戶界面,能實現(xiàn)一個聊天室中多人聊天,可以兩人私聊。
QQ:實現(xiàn)類似QQ登錄、聊天等功能。
注意:有一定等級。完全照搬別人的代碼,不超過70分。
提示:使用socket通信
前面是逐步講解,要是想看最終代碼,請直接找到該文章的最下面
//
感謝這位up博主的視頻講解?。。?br>準備工作
建立包,類,文件
插入圖片要創(chuàng)建一個文件夾,文件夾里保存的就是所需要的圖片啦,比如我創(chuàng)建的文件夾為image;
兩個設備上進行通信,要用到socket通信協(xié)議,即客戶端的內容先傳到服務器,在服務器上處理,傳回客戶端

java實現(xiàn)qq聊天(超詳細)
image素材文件里存放的圖片
鏈接:https://pan.baidu.com/s/1zns86NC6Qm80xKZHMIRSbA
提取碼:3f6w
java實現(xiàn)qq聊天(超詳細)

//

1.首先我們先建一個qq登陸界面

成品圖如下:
java實現(xiàn)qq聊天(超詳細)
詳細代碼及注釋如下

// 客戶端的登陸界面
package com.qq.client.view;
//抽象窗口工具包
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class QqClientlLogin  extends JFrame{  //JFrame的子類
	
	  JLabel jup;   //定義上部需要的組件   //標簽
	
	//定義中部需要的組件
	  JPanel jmid ;
      JLabel jmid_num1,jmid_key1;
      JTextField jmid_num2;    //文本框
      JPasswordField jmid_key2;   //密碼框
      JCheckBox jmid_rember,jmid_automatic;  //復選框
	  
	 JPanel  jdown;         //JPanel 面板
	 JButton jdown_1,jdown_2;    //定義下部需要的組件
	 
	 public  QqClientlLogin()      //構造方法
	 {
		  //處理上部      
	    jup=new JLabel(new  ImageIcon("image/up3.png"));
	
	    //處理中部
	    jmid=new JPanel(new GridLayout(3,3));//網格布局 3行3列
	    Font font = new Font("宋體", Font.PLAIN, 25);    //創(chuàng)建1個字體實例
	    jmid_num1=new JLabel("QQ號碼:",JLabel.CENTER);  
	    jmid_key1=new JLabel("QQ密碼:",JLabel.CENTER);
	    jmid_num1.setFont(font);    jmid_key1.setFont(font);  //字體大小
        jmid_num2= new JTextField() ;    
	    jmid_key2=new JPasswordField();
	    jmid_rember=new JCheckBox("自動登錄");
	    jmid_automatic=new JCheckBox("記住密碼");
	    jmid_rember.setFont(font);    jmid_automatic.setFont(font); //字體大小
	    jmid_rember.setForeground(Color.blue); 	  //設置字體顏色
	    jmid_automatic.setForeground(Color.blue);
	    jmid.add(jmid_num1);
	    jmid.add(jmid_num2);
	    jmid.add(jmid_key1);
	    jmid.add(jmid_key2);
	    jmid.add(jmid_rember);
	    jmid.add(jmid_automatic);
	    
	    //處理下部
	    jdown=new JPanel(new FlowLayout()); //流式布局
	    jdown_1=new JButton(new ImageIcon("image/denglu.png"));
	    jdown_2=new JButton(new ImageIcon("image/tuichu.png"));
	    jdown.add(jdown_1);
	    jdown.add(jdown_2);
	    
	    setLocation(300,300); //窗口的位置
	    add(jup,"North");   //放在最北部    
	    add(jmid,"Center");  //放在中間
	    add(jdown,"South"); //放在南部
	    setSize(700,540);     //設置大小                                  
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //結束窗口所在的應用程序  
	    setVisible(true);       //可見,默認是不可見
	 }
	 
	 public static void main(String[]  args)
	 {
		 QqClientlLogin  qqClientlLogin=new  QqClientlLogin();
	 } 
}

//

2.好友列表界面

成品圖如下:
java實現(xiàn)qq聊天(超詳細)

要建立兩個卡片的轉換,即點擊卡片一的"黑名單"轉到第二個卡片界面,點擊第二個卡片的"我的好友",轉到第一個界面上
此時,就需要創(chuàng)建監(jiān)聽器的類,用到ActionListener接口
除此之外,我還建立了鼠標監(jiān)聽MouseListener接口,當鼠標停留在好友是,好友編號變紅,離開時變回黑色,雙擊好友時,可得到該好友的編號(并進入與該好友的聊天界面)
詳細代碼及注釋如下

//好友列表(也包括黑名單)
package com.qq.client.view;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class QqFriendList extends JFrame implements ActionListener,MouseListener {   
	//負責創(chuàng)建監(jiān)聽器的類,  點擊按鈕觸發(fā)ActionListener事件;  鼠標監(jiān)聽MouseListener 
	
    // 第一張卡片(我的好友);
		JPanel jup1,jmid1,jdown1;   //jup1即為總JPanel;
		JButton jup1_1,jdown1_1;
		JScrollPane jmid1_1;      //滑動窗口;
	
	//第二張卡片(黑名單);
		JPanel jup2,jup2_button,jmid2;
		JButton jup2_1,jup2_2;
		JScrollPane jmid2_1;      //滑動窗口;
		
  //把整個JFrame設置成CardLayout布局
		CardLayout cl;

   public  QqFriendList ()
   {         Font font = new Font("宋體", Font.PLAIN, 35);    //創(chuàng)建字體實例

	
	   //處理第一張卡片(我的好友);
	    jup1=new JPanel(new BorderLayout());   //第一張卡片的總JPane,BorderLayout()布局;
	   jup1_1=new JButton("我的好友");
	   jup1_1.setFont(font);  //字體
	
	   //假設有50個好友,具體是服務器返回的結果(好友信息存放在服務器)
	   jmid1=new JPanel(new  GridLayout(50,1,4,4));  //(4,4)行間距和列間距
       //給jmid1初始化50個好友
	   JLabel []jlist1=new JLabel [50];  //數(shù)組;
	   for ( int i=0; i<jlist1.length ; i++ )
	   {
		   jlist1[i]=new JLabel(i+1+" ",new ImageIcon("image/touxiang.png"),JLabel.LEFT);
		   jlist1[i].addMouseListener(this);
		   jmid1.add(jlist1[i]);  
	   }
	   jmid1_1=new JScrollPane(jmid1);
	   
	   jdown1_1=new JButton("黑名單");
	   jdown1_1.addActionListener(this);     //給jdown1_1按鈕增加一個監(jiān)聽器,這個監(jiān)聽器對象就是“QqFriendList ”類型的,
	                          //當用戶點擊了jdown1_1按鈕時,會程序自動前往QqFriendList類的“actionPerformed”方法中,處理產生的事件。
	   jdown1_1.setFont(font);        //字體
	   jdown1=new JPanel(new GridLayout(1,1));//黑名單按鈕
	   jdown1.add(jdown1_1);  //加入按鈕;
	   
       jup1.add(jup1_1,"North");
       jup1.add(jmid1_1,"Center");
       jup1.add(jdown1,"South");
   

       
       //處理第二張卡片(黑名單)	   
       jup2=new JPanel(new BorderLayout());   //第二張卡片的總JPane,BorderLayout()布局;
       jup2_1=new JButton("我的好友");
       jup2_1.addActionListener(this);   //監(jiān)聽
       jup2_2=new JButton("黑名單");
	   jup2_1.setFont(font);  //字體
       jup2_2.setFont(font);
       jup2_button=new JPanel(new GridLayout(2,1));//黑名單按鈕
       jup2_button.add(jup2_1);
       jup2_button.add(jup2_2);
       
	   //假設有20個黑名單,具體是服務器返回的結果(好友信息存放在服務器)
	   jmid2=new JPanel(new  GridLayout(20,1,4,4));  //(4,4)行間距和列間距
       //給jmid2初始化20個好友
	   JLabel []jlist2=new JLabel [20];  //數(shù)組;
	   for ( int i=0; i<jlist2.length ; i++ )
	   {
		   jlist2[i]=new JLabel(i+1+" ",new ImageIcon("image/heitou.png"),JLabel.LEFT);
		   jmid2.add(jlist2[i]);
	   }
	   jmid2_1=new JScrollPane(jmid2);
	   
       jup2.add(jup2_button,"North");
       jup2.add(jmid2_1);
  
       cl=new CardLayout();
       setLayout(cl);
       add(jup1,"1");  //第一張卡片jup1;
       add(jup2,"2");  //第二張卡片jup2;
       setLocation(300,300); //窗口的位置
       setSize(440,800);
       setVisible(true);     
   }
  
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		QqFriendList  qqFriendList=new  QqFriendList();
	}
	
	public void actionPerformed(ActionEvent arg0)
	{ 
		//如果點擊了黑名單按鈕,就顯示第二張卡片
		if(arg0.getSource()==jdown1_1)
		{
			cl.show(this.getContentPane(), "2");  //用getContentPane()方法獲得JFrame的內容面板
		}
		else
			if(arg0.getSource()==jup2_1)
			{
				cl.show(this.getContentPane(), "1");
			}
	}
	public void mouseEntered(MouseEvent arg0) {    //進入組件觸發(fā)鼠標事件
		// TODO Auto-generated method stub
		JLabel jl=(JLabel)arg0.getSource(); //變成JLable形式
                                              //getSource()獲取鼠標事件的事件源;
		jl.setForeground(Color.red);   //設置前景色
	}

	public void mouseExited(MouseEvent arg0) {  //鼠標離開組件觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
		JLabel jl=(JLabel)arg0.getSource();   
		jl.setForeground(Color.black);
	}
	
	public void mouseClicked(MouseEvent arg0) {   //點擊鼠標觸發(fā)鼠的標事件
		// TODO Auto-generated method stub
		//響應用戶雙擊的事件,并得到好友的編號.
		if(arg0.getClickCount()==2)   //getClickCount() 獲取鼠標被單機的次數(shù)
		{
			//得到該好友的編號 
			//getText() 的意思是:返回數(shù)據(jù)窗口控件中 懸浮在當前行列之上的
			String friendNum=((JLabel)arg0.getSource()).getText();
			
			//System.out.println("你希望和 "+friendNum+" 聊天");
		}
	}


	public void mousePressed(MouseEvent arg0) { //按下按鼠標鍵觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
		
	}

	public void mouseReleased(MouseEvent arg0) {   //釋放鼠標鍵觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
		
	}

} 

3.聊天界面,用服務器判斷登錄qq,對象流

這部分的代碼成果圖:
java實現(xiàn)qq聊天(超詳細)

注:正常是要有數(shù)據(jù)庫來存qq賬號密碼信息的,秉著由簡至難的原則,此處先不設計數(shù)據(jù)庫,直接用服務器判斷
有了上訴兩個界面的設置,相信設置聊天界面應該很好模擬退出
聊天界面初步成果:java實現(xiàn)qq聊天(超詳細)

//與好友聊天的界面
package com.qq.client.view;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class QqChat extends JFrame {
	 Font font = new Font("宋體", Font.PLAIN, 20); 
	JTextArea jta;    //文本域  存聊天內容
	JTextField jtf;    //文本框
	JButton jb;
	JPanel jp;
	String ownerId;
	String friendId;
	
	public QqChat(String owner,String friend)
	{
		jta=new JTextArea();
		jtf=new JTextField(25);     //25個字符那么寬
		jb=new JButton("發(fā)送");
		jb.setFont(font);
		jp=new JPanel();
		jp.add(jtf);
		jp.add(jb);	
		add(jta,"Center");
		add(jp,"South");
		setTitle(owner+"正在和 "+friend+" 聊天");  //設置標題
		setIconImage((new ImageIcon("image/qq.png").getImage())); //獲取圖像
		setLocation(800,400); //窗口的位置
		setSize(600, 500);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
	    QqChat qqChat=new QqChat("1");   //傳入好友1,你正在和1聊天;
	}

思考一下,如果是要與其余好友聊天應該如何表示呢?
在 QqFriendList中,我們雙擊得到好友的編號,只需把編號傳到QqChat中即可
java實現(xiàn)qq聊天(超詳細)
現(xiàn)在來實現(xiàn)登錄操作:當用戶點擊登錄后,把qq號碼和密碼發(fā)送給QqServer(服務器)去驗證,如果該用戶合法,返回true,否則返回false;
以對象流的方式讀取客戶端發(fā)來的賬號和密碼,在網絡間傳遞對象流,
避免直接讀入由特殊符號,空格,換行等干擾

對象流是一種高級流,可以方便我們將java中的任何對象進行讀寫操作。
java.io.objectoutputstream對象輸出流,可以將對象轉換為一組字節(jié)寫出。
java.io.objectinputstream對象輸入流,可以讀取一組字節(jié)轉換為原對象,
還原為原對象的條件是讀取這個字節(jié)應該是對象輸出流將一個對象轉換的字節(jié)。

一個對象要想序列化,該類必須實現(xiàn)java.io.Serializable 接口
Serializable 是一個標記接口,不實現(xiàn)此接口的類將不會使任何狀態(tài)序列化或反序列化,會拋出NotSerializableException 。
使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中

在這里,我們還要用到socket socket是兩臺主機之間的一個連接
網絡上的兩個程序通過一個雙向的通信連接實現(xiàn)數(shù)據(jù)的交換,這個連接的一端稱為一個socket。
建立網絡通信連接需要一對socket,兩個socket之間形成一個管道(通道),進行信息流的傳輸(聯(lián)想IO流中文件和程序之間讀寫)。

ServerSocket與Socket入門詳解
分別在Qqclient(客戶端)和QqServe(服務端)項目里建立com.qq.common包,包里存放Message.java和User.java兩個類
User類就是獲得用戶輸入的賬號和密碼

//用戶信息類
package com.qq.common;

public class User  implements java.io.Serializable{
	 
	private String userId;
	private String passwd;
	public String getUserId()
	{
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getPasswd()
	{
		return passwd;
	}
	public void setPasswd(String passwd)
	{
		this.passwd=passwd;
	}
}

對發(fā)送服務端的信息規(guī)定一些規(guī)則
mesType為true 表明登陸成功
mesType為false 表明登錄失敗
所以Message就是用來判斷的

package com.qq.common;
public class Message implements java.io.Serializable { //序列化     
	private String mesType;
	public String getMesType()
	{
		return mesType;
	}
	public void setMesType(String mesType)
	{
		this.mesType =mesType;
	}
}

主要思想
java實現(xiàn)qq聊天(超詳細)
要在第一部分qq登錄界面的代碼中加上監(jiān)聽(登錄按鈕),將得到的賬戶和密碼信息逐步傳入到破服務器里面,再有服務器返回,判斷是否能登錄,如果能,打開好友列表界面,
否則,觸發(fā)提示框"用戶名或密碼錯誤".
客戶端
注意:我判斷的是如果密碼為"123456"即為正確

// 客戶端的登陸界面
package com.qq.client.view;
//抽象窗口工具包
import javax.swing.*;
import java.awt.*;  
import java.awt.event.*;
import com.qq.client.model.*;
import com.qq.common.*;
public class QqClientlLogin  extends JFrame implements ActionListener{  //JFrame的子類
	
	  JLabel jup;   //定義上部需要的組件   //標簽
	
	//定義中部需要的組件
	  JPanel jmid ;
      JLabel jmid_num1,jmid_key1;
      JTextField jmid_num2;    //文本框
      JPasswordField jmid_key2;   //密碼框
      JCheckBox jmid_rember,jmid_automatic;  //復選框
	  
	 JPanel  jdown;         //JPanel 面板
	 JButton jdown_1,jdown_2;    //定義下部需要的組件
	 
	 public  QqClientlLogin()      //構造方法
	 {
		  //處理上部      
	    jup=new JLabel(new  ImageIcon("image/up3.png"));
	
	    //處理中部
	    jmid=new JPanel(new GridLayout(3,3));//網格布局 3行3列
	    Font font = new Font("宋體", Font.PLAIN, 25);    //創(chuàng)建1個字體實例
	    jmid_num1=new JLabel("QQ號碼:",JLabel.CENTER);  
	    jmid_key1=new JLabel("QQ密碼:",JLabel.CENTER);
	    jmid_num1.setFont(font);    jmid_key1.setFont(font);  //字體大小
        jmid_num2= new JTextField() ;    
	    jmid_key2=new JPasswordField();
	    jmid_rember=new JCheckBox("自動登錄");
	    jmid_automatic=new JCheckBox("記住密碼");
	    jmid_rember.setFont(font);    jmid_automatic.setFont(font); //字體大小
	    jmid_rember.setForeground(Color.blue); 	  //設置字體顏色
	    jmid_automatic.setForeground(Color.blue);
	    jmid.add(jmid_num1);
	    jmid.add(jmid_num2);
	    jmid.add(jmid_key1);
	    jmid.add(jmid_key2);
	    jmid.add(jmid_rember);
	    jmid.add(jmid_automatic);
	    
	    //處理下部
	    jdown=new JPanel(new FlowLayout()); //流式布局
	    jdown_1=new JButton(new ImageIcon("image/denglu.png"));
	    
	    //響應用戶點擊登錄
	    jdown_1.addActionListener(this);  //監(jiān)控
	    
	    jdown_2=new JButton(new ImageIcon("image/tuichu.png"));
	    jdown.add(jdown_1);
	    jdown.add(jdown_2);
	    
	    setLocation(300,300); //窗口的位置
	    add(jup,"North");   //放在最北部    
	    add(jmid,"Center");  //放在中間
	    add(jdown,"South"); //放在南部
	    setSize(700,540);     //設置大小                                  
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //結束窗口所在的應用程序  
	    setVisible(true);       //可見,默認是不可見
	 }
	 
	 public static void main(String[]  args)
	 {
		 QqClientlLogin  qqClientlLogin=new  QqClientlLogin();
	 } 
	public void actionPerformed(ActionEvent arg0)
	{
		if(arg0.getSource()==jdown_1);   //請求登錄
		{
	     	User u=new User();
	     	u. setUserId(jmid_num2.getText().trim());   //trim() 方法用于 刪除字符串的頭尾空白符
	     	u. setPasswd(new String (jmid_key2.getPassword()));   //字符串;
	    	QqClientUser qqclientuser=new QqClientUser();
	    	
	     	if(qqclientuser.checkUser(u))
	     	{
	     		new QqFriendList(u.getUserId());  //好友列表
	     		this.dispose();  //關閉登陸界面
	     	}
	     	else
	     	{
	     		JOptionPane.showMessageDialog(this,"用戶名或密碼錯誤");
	     		//JOptionPane彈窗,消息提示框
	     		//showMessageDialog這個方法里有兩個參數(shù)
	     		//第一個參數(shù)-確定Frame在其中顯示的對話框
	     		//第二個參數(shù)message就是我們要在提示框里顯示的信息
	     	}
		}
	}
}


//好友列表(也包括黑名單)
package com.qq.client.view;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class QqFriendList extends JFrame implements ActionListener,MouseListener {   
	//負責創(chuàng)建監(jiān)聽器的類,  點擊按鈕觸發(fā)ActionListener事件;  鼠標監(jiān)聽MouseListener 
	    
	     String owner;      
	     
    // 第一張卡片(我的好友);
		JPanel jup1,jmid1,jdown1;   //jup1即為總JPanel;
		JButton jup1_1,jdown1_1;
		JScrollPane jmid1_1;      //滑動窗口;
	
	//第二張卡片(黑名單);
		JPanel jup2,jup2_button,jmid2;
		JButton jup2_1,jup2_2;
		JScrollPane jmid2_1;      //滑動窗口;
		
  //把整個JFrame設置成CardLayout布局
		CardLayout cl;

   public  QqFriendList (String ownerId)
   {   
	   Font font = new Font("宋體", Font.PLAIN, 35);    //創(chuàng)建字體實例

	    owner=ownerId;
	   //處理第一張卡片(我的好友);
	    jup1=new JPanel(new BorderLayout());   //第一張卡片的總JPane,BorderLayout()布局;
	   jup1_1=new JButton("我的好友");
	   jup1_1.setFont(font);  //字體
	
	   //假設有50個好友,具體是服務器返回的結果(好友信息存放在服務器)
	   jmid1=new JPanel(new  GridLayout(50,1,4,4));  //(4,4)行間距和列間距
       //給jmid1初始化50個好友
	   JLabel []jlist1=new JLabel [50];  //數(shù)組;
	   for ( int i=0; i<jlist1.length ; i++ )
	   {
		   jlist1[i]=new JLabel(i+1+"",new ImageIcon("image/touxiang.png"),JLabel.LEFT);
		   jlist1[i].addMouseListener(this);
		   jmid1.add(jlist1[i]);  
	   }
	   jmid1_1=new JScrollPane(jmid1);
	   
	   jdown1_1=new JButton("黑名單");
	   jdown1_1.addActionListener(this);     //給jdown1_1按鈕增加一個監(jiān)聽器,這個監(jiān)聽器對象就是“QqFriendList ”類型的,
	                          //當用戶點擊了jdown1_1按鈕時,會程序自動前往QqFriendList類的“actionPerformed”方法中,處理產生的事件。
	   jdown1_1.setFont(font);        //字體
	   jdown1=new JPanel(new GridLayout(1,1));//黑名單按鈕
	   jdown1.add(jdown1_1);  //加入按鈕;
	   
       jup1.add(jup1_1,"North");
       jup1.add(jmid1_1,"Center");
       jup1.add(jdown1,"South");
   

       
       //處理第二張卡片(黑名單)	   
       jup2=new JPanel(new BorderLayout());   //第二張卡片的總JPane,BorderLayout()布局;
       jup2_1=new JButton("我的好友");
       jup2_1.addActionListener(this);   //監(jiān)聽
       jup2_2=new JButton("黑名單");
	   jup2_1.setFont(font);  //字體
       jup2_2.setFont(font);
       jup2_button=new JPanel(new GridLayout(2,1));//黑名單按鈕
       jup2_button.add(jup2_1);
       jup2_button.add(jup2_2);
       
	   //假設有20個黑名單,具體是服務器返回的結果(好友信息存放在服務器)
	   jmid2=new JPanel(new  GridLayout(20,1,4,4));  //(4,4)行間距和列間距
       //給jmid2初始化20個好友
	   JLabel []jlist2=new JLabel [20];  //數(shù)組;
	   for ( int i=0; i<jlist2.length ; i++ )
	   {
		   jlist2[i]=new JLabel(i+1+" ",new ImageIcon("image/heitou.png"),JLabel.LEFT);
		   jmid2.add(jlist2[i]);
	   }
	   jmid2_1=new JScrollPane(jmid2);
	   
       jup2.add(jup2_button,"North");
       jup2.add(jmid2_1);
  
       cl=new CardLayout();
       setLayout(cl);
       add(jup1,"1");  //第一張卡片jup1;
       add(jup2,"2");  //第二張卡片jup2;
        setTitle(ownerId);//顯示自己的編號
       setLocation(300,300); //窗口的位置
       setSize(440,800);
       setVisible(true);     
   }
  
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		QqFriendList  qqFriendList=new  QqFriendList();
	}
	
	public void actionPerformed(ActionEvent arg0)
	{ 
		//如果點擊了黑名單按鈕,就顯示第二張卡片
		if(arg0.getSource()==jdown1_1)
		{
			cl.show(this.getContentPane(), "2");  //用getContentPane()方法獲得JFrame的內容面板
		}
		else
			if(arg0.getSource()==jup2_1)
			{
				cl.show(this.getContentPane(), "1");
			}
	}
	public void mouseEntered(MouseEvent arg0) {    //進入組件觸發(fā)鼠標事件
		// TODO Auto-generated method stub
		JLabel jl=(JLabel)arg0.getSource(); //變成JLable形式
                                              //getSource()獲取鼠標事件的事件源;
		jl.setForeground(Color.red);   //設置前景色
	}

	public void mouseExited(MouseEvent arg0) {  //鼠標離開組件觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
		JLabel jl=(JLabel)arg0.getSource();   
		jl.setForeground(Color.black);
	}
	
	public void mouseClicked(MouseEvent arg0) {   //點擊鼠標觸發(fā)鼠的標事件
		// TODO Auto-generated method stub
		//響應用戶雙擊的事件,并得到好友的編號.
		if(arg0.getClickCount()==2)   //getClickCount() 獲取鼠標被單機的次數(shù)
		{
			//得到該好友的編號 
			//getText() 的意思是:返回數(shù)據(jù)窗口控件中 懸浮在當前行列之上的
			String friendNum=((JLabel)arg0.getSource()).getText();
			
			//System.out.println("你希望和 "+friendNum+" 聊天");
			new QqChat(owner,friendNum);  //傳入編號
		}
	}

	public void mousePressed(MouseEvent arg0) { //按下按鼠標鍵觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
	}

	public void mouseReleased(MouseEvent arg0) {   //釋放鼠標鍵觸發(fā)的鼠標事件
		// TODO Auto-generated method stub		
	}
} 

package com.qq.client.model;
import com.qq.common.*;
public class QqClientUser {
  
	  public boolean checkUser(User u)
	  {
		 return new QqClientConServer().sendLoginInfotoSSErver(u);
	  }
}

//客戶端鏈接服務器的部分
package com.qq.client.model;

import java.util.*;
import java.net.*;
import java.io.*;
import com.qq.common.*;
public class QqClientConServer{
 
	//發(fā)送第一次請求,登錄請求
	public boolean sendLoginInfotoSSErver(Object o) //發(fā)送對象到服務器
	{  
		boolean b=false;
		try
		 { 
			 Socket s=new Socket("127.0.0.1",9999);	 //傳入要連接主機與端口
			 ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream()); //輸出流
		     oos.writeObject(o);  //把o發(fā)出去
			 
		     ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
		     Message ms=(Message)ois.readObject();  
		     if(ms.getMesType().equals("1"))
		    	b=true;
		 }
		 catch (Exception e)
		 {
			 e.printStackTrace();
		 }
		 finally
		 {
		 }
		return b;
	}
}

服務端
除了需要的Message.java和User.java兩個類還需要

//服務器端控制界面,可以完成啟動服務器,關閉服務器,可以管理和監(jiān)控用戶
package com.qq.server.view;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.qq.server.model.MyQqServer;
public class ControlPanel  extends JFrame implements ActionListener{
    
	JPanel jp1;
	JButton jstart,jend;

	public ControlPanel()
	{   Font font = new Font("宋體",Font.PLAIN,30);
	
		jp1=new JPanel();
		jstart=new JButton("啟動服務器");
		jstart.addActionListener(this);
		jend=new JButton("關閉服務器");
		jstart.setFont(font); jend.setFont(font);
		jstart.setForeground(Color.BLUE); jend.setForeground(Color.BLUE);
		
		jp1.add(jstart);
		jp1.add(jend);
		
		add(jp1);
		setLocation(150,150);
		setSize(900,900);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //結束窗口所在的應用程序  
		setVisible(true);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ControlPanel controlpanel =new ControlPanel();
	}
	
	public void actionPerformed(ActionEvent arg0)
	{
		if(arg0.getSource()==jstart)
		{
			new MyQqServer();
		}
	}
}

//qq服務器,監(jiān)聽,等待某個qq客戶端鏈接
package com.qq.server.model;

import java.io.*; //(I/O)流庫,提供大量的流類
import java.net.*;//導入網絡包
import java.util.*; //實用工具類,提供了一些實用的方法和數(shù)據(jù)結構
import com.qq.common.*;

public class MyQqServer  {

	public MyQqServer ()
	{
		//try-catch語句處理異常
        try
        { 
        	//ServerSocket類表示服務器socket
        	//在9999監(jiān)聽
    		System.out.println("服務器正在9999監(jiān)聽");//簡單判斷一下是否啟動服務端
        	ServerSocket ss=new ServerSocket(9999);
        while(true)   //服務器可多次監(jiān)聽
        {
            Socket s=ss.accept() ;  //阻塞,等待連接(與客戶端)
        	//接收客戶端發(fā)來的信息
           ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
            User u=(User)ois.readObject();
            System.out.println("用戶Id:"+u.getUserId()+"  密碼"+u.getPasswd()); 
          	Message m=new Message();
          	 ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
            if(u.getPasswd().equals("123456"))
            {
            	//返回一個成功登錄的信息
            	m.setMesType("1");    //mesType1 =1  表明登陸成功
                oos.writeObject(m);  
            }
            else
            {
            	m.setMesType("2"); 
                oos.writeObject(m); 
                s.close();  //關閉連接(流)
            }
        }
       }
        catch(Exception e)
        {
        	e.printStackTrace();//將錯誤信息全部打印
        }
        finally{
        	
        }
	}
}

4.一對一的聊天

java實現(xiàn)qq聊天(超詳細)

進程概念:進程是代碼在數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進行資源分配和調度的基本單位。
線程概念:線程是進程的一個執(zhí)行路徑,一個進程中至少有一個線程,進程中的多個線程共享進程的資源。

此處要用線程用來接收客戶端的消息,因為不僅僅一個用戶(可實現(xiàn)多用戶登錄)
要在message類里面加入,用戶編號,接受方,發(fā)送信息(即獲得聊天界面文本框的內容)等
在chat類里面,加入讀取,文本域中顯示聊天代碼等內容
在管理客戶端線程中使用HashMap<關鍵字,值>記錄發(fā)送者與服務器的socket,關鍵字記錄用戶編號,值記錄socket

每個包(類)或多或少都有所更改,完整代碼如下,希望對大家有所幫助,同時請大佬指正錯誤%%%

//
客戶端代碼

package com.qq.common;

public class Message implements java.io.Serializable { //序列化
     
	private String mesType;
	
	private String sender;//發(fā)送者
	private String getter; //接收者
	private String con;  //信息
	
	public String getSender()
	{
		return sender;
	}
	public void setSender(String sender)
	{
		this.sender=sender;
	}
	
	public String getGetter()
	{
		return getter;
	}
	public void setGetter(String getter)
	{
		this.getter=getter;
	}
	
	public String getCon()
	{
		return con;
	}
	public void setCon(String con)
	{
		this.con=con;
	}
	
	public String getMesType()
	{
		return mesType;
	}
	public void setMesType(String mesType)
	{
		this.mesType =mesType;
	}
}

//用戶信息類
package com.qq.common;

public class User  implements java.io.Serializable{
	 
	private String userId;
	private String passwd;
	public String getUserId()
	{
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getPasswd()
	{
		return passwd;
	}
	public void setPasswd(String passwd)
	{
		this.passwd=passwd;
	}
	
}
// 客戶端的登陸界面
package com.qq.client.view;
//抽象窗口工具包
import javax.swing.*;
import java.awt.*;  
import java.awt.event.*;
import com.qq.client.model.*;
import com.qq.common.*;
public class QqClientlLogin  extends JFrame implements ActionListener{  //JFrame的子類
	
	  JLabel jup;   //定義上部需要的組件   //標簽
	
	//定義中部需要的組件
	  JPanel jmid ;
      JLabel jmid_num1,jmid_key1;
      JTextField jmid_num2;    //文本框
      JPasswordField jmid_key2;   //密碼框
      JCheckBox jmid_rember,jmid_automatic;  //復選框
	  
	 JPanel  jdown;         //JPanel 面板
	 JButton jdown_1,jdown_2;    //定義下部需要的組件
	 
	 public  QqClientlLogin()      //構造方法
	 {
		  //處理上部      
	    jup=new JLabel(new  ImageIcon("image/up3.png"));
	
	    //處理中部
	    jmid=new JPanel(new GridLayout(3,3));//網格布局 3行3列
	    Font font = new Font("宋體", Font.PLAIN, 25);    //創(chuàng)建1個字體實例
	    jmid_num1=new JLabel("QQ號碼:",JLabel.CENTER);  
	    jmid_key1=new JLabel("QQ密碼:",JLabel.CENTER);
	    jmid_num1.setFont(font);    jmid_key1.setFont(font);  //字體大小
        jmid_num2= new JTextField() ;    
	    jmid_key2=new JPasswordField();
	    jmid_rember=new JCheckBox("自動登錄");
	    jmid_automatic=new JCheckBox("記住密碼");
	    jmid_rember.setFont(font);    jmid_automatic.setFont(font); //字體大小
	    jmid_rember.setForeground(Color.blue); 	  //設置字體顏色
	    jmid_automatic.setForeground(Color.blue);
	    jmid.add(jmid_num1);
	    jmid.add(jmid_num2);
	    jmid.add(jmid_key1);
	    jmid.add(jmid_key2);
	    jmid.add(jmid_rember);
	    jmid.add(jmid_automatic);
	    
	    //處理下部
	    jdown=new JPanel(new FlowLayout()); //流式布局
	    jdown_1=new JButton(new ImageIcon("image/denglu.png"));
	    
	    //響應用戶點擊登錄
	    jdown_1.addActionListener(this);  //監(jiān)控
	    
	    jdown_2=new JButton(new ImageIcon("image/tuichu.png"));
	    jdown.add(jdown_1);
	    jdown.add(jdown_2);
	    
	    setLocation(300,300); //窗口的位置
	    add(jup,"North");   //放在最北部    
	    add(jmid,"Center");  //放在中間
	    add(jdown,"South"); //放在南部
	    setSize(700,540);     //設置大小                                  
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //結束窗口所在的應用程序  
	    setVisible(true);       //可見,默認是不可見
	 }
	 
	 public static void main(String[]  args)
	 {
		 QqClientlLogin  qqClientlLogin=new  QqClientlLogin();
	 } 
	public void actionPerformed(ActionEvent arg0)
	{
		if(arg0.getSource()==jdown_1);   //請求登錄
		{
	     	User u=new User();
	     	u. setUserId(jmid_num2.getText().trim());   //trim() 方法用于 刪除字符串的頭尾空白符
	     	u. setPasswd(new String (jmid_key2.getPassword()));   //字符串;
	    	QqClientUser qqclientuser=new QqClientUser();
	    	
	     	if(qqclientuser.checkUser(u))
	     	{
	     		QqFriendList qqList=new QqFriendList(u.getUserId());  //好友列表
	     		this.dispose();  //關閉登陸界面
	     	}
	     	else
	     	{
	     		JOptionPane.showMessageDialog(this,"用戶名或密碼錯誤");
	     		//JOptionPane彈窗,消息提示框
	     		//showMessageDialog這個方法里有兩個參數(shù)
	     		//第一個參數(shù)-確定Frame在其中顯示的對話框
	     		//第二個參數(shù)message就是我們要在提示框里顯示的信息
	     	}
		}
	}
}

//好友列表(也包括黑名單)
package com.qq.client.view;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class QqFriendList extends JFrame implements ActionListener,MouseListener {   
	//負責創(chuàng)建監(jiān)聽器的類,  點擊按鈕觸發(fā)ActionListener事件;  鼠標監(jiān)聽MouseListener 
	    
	     String owner;      
	     
    // 第一張卡片(我的好友);
		JPanel jup1,jmid1,jdown1;   //jup1即為總JPanel;
		JButton jup1_1,jdown1_1;
		JScrollPane jmid1_1;      //滑動窗口;
	
	//第二張卡片(黑名單);
		JPanel jup2,jup2_button,jmid2;
		JButton jup2_1,jup2_2;
		JScrollPane jmid2_1;      //滑動窗口;
		
  //把整個JFrame設置成CardLayout布局
		CardLayout cl;

   public  QqFriendList (String ownerId)
   {   
	   Font font = new Font("宋體", Font.PLAIN, 35);    //創(chuàng)建字體實例

	    owner=ownerId;
	   //處理第一張卡片(我的好友);
	    jup1=new JPanel(new BorderLayout());   //第一張卡片的總JPane,BorderLayout()布局;
	   jup1_1=new JButton("我的好友");
	   jup1_1.setFont(font);  //字體
	
	   //假設有50個好友,具體是服務器返回的結果(好友信息存放在服務器)
	   jmid1=new JPanel(new  GridLayout(50,1,4,4));  //(4,4)行間距和列間距
       //給jmid1初始化50個好友
	   JLabel []jlist1=new JLabel [50];  //數(shù)組;
	   for ( int i=0; i<jlist1.length ; i++ )
	   {
		   jlist1[i]=new JLabel(i+1+" ",new ImageIcon("image/touxiang.png"),JLabel.LEFT);
		   jlist1[i].addMouseListener(this);
		   jmid1.add(jlist1[i]);  
	   }
	   jmid1_1=new JScrollPane(jmid1);
	   
	   jdown1_1=new JButton("黑名單");
	   jdown1_1.addActionListener(this);     //給jdown1_1按鈕增加一個監(jiān)聽器,這個監(jiān)聽器對象就是“QqFriendList ”類型的,
	                          //當用戶點擊了jdown1_1按鈕時,會程序自動前往QqFriendList類的“actionPerformed”方法中,處理產生的事件。
	   jdown1_1.setFont(font);        //字體
	   jdown1=new JPanel(new GridLayout(1,1));//黑名單按鈕
	   jdown1.add(jdown1_1);  //加入按鈕;
	   
       jup1.add(jup1_1,"North");
       jup1.add(jmid1_1,"Center");
       jup1.add(jdown1,"South");
   

       
       //處理第二張卡片(黑名單)	   
       jup2=new JPanel(new BorderLayout());   //第二張卡片的總JPane,BorderLayout()布局;
       jup2_1=new JButton("我的好友");
       jup2_1.addActionListener(this);   //監(jiān)聽
       jup2_2=new JButton("黑名單");
	   jup2_1.setFont(font);  //字體
       jup2_2.setFont(font);
       jup2_button=new JPanel(new GridLayout(2,1));//黑名單按鈕
       jup2_button.add(jup2_1);
       jup2_button.add(jup2_2);
       
	   //假設有20個黑名單,具體是服務器返回的結果(好友信息存放在服務器)
	   jmid2=new JPanel(new  GridLayout(20,1,4,4));  //(4,4)行間距和列間距
       //給jmid2初始化20個好友
	   JLabel []jlist2=new JLabel [20];  //數(shù)組;
	   for ( int i=0; i<jlist2.length ; i++ )
	   {
		   jlist2[i]=new JLabel(i+1+" ",new ImageIcon("image/heitou.png"),JLabel.LEFT);
		   jmid2.add(jlist2[i]);
	   }
	   jmid2_1=new JScrollPane(jmid2);
	   
       jup2.add(jup2_button,"North");
       jup2.add(jmid2_1);
  
       cl=new CardLayout();
       setLayout(cl);
       add(jup1,"1");  //第一張卡片jup1;
       add(jup2,"2");  //第二張卡片jup2;
        setTitle(ownerId);//顯示自己的編號
       setLocation(300,300); //窗口的位置
       setSize(440,800);
       setVisible(true);     
   }
 
   public static void main(String[] args) {
		// TODO Auto-generated method stub
		//QqFriendList  qqFriendList=new  QqFriendList();
	} 
   
	public void actionPerformed(ActionEvent arg0)
	{ 
		//如果點擊了黑名單按鈕,就顯示第二張卡片
		if(arg0.getSource()==jdown1_1)
		{
			cl.show(this.getContentPane(), "2");  //用getContentPane()方法獲得JFrame的內容面板
		}
		else
			if(arg0.getSource()==jup2_1)
			{
				cl.show(this.getContentPane(), "1");
			}
	}
	public void mouseEntered(MouseEvent arg0) {    //進入組件觸發(fā)鼠標事件
		// TODO Auto-generated method stub
		JLabel jl=(JLabel)arg0.getSource(); //變成JLable形式
                                              //getSource()獲取鼠標事件的事件源;
		jl.setForeground(Color.red);   //設置前景色
	}

	public void mouseExited(MouseEvent arg0) {  //鼠標離開組件觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
		JLabel jl=(JLabel)arg0.getSource();   
		jl.setForeground(Color.black);
	}
	
	public void mouseClicked(MouseEvent arg0) {   //點擊鼠標觸發(fā)鼠的標事件
		// TODO Auto-generated method stub
		//響應用戶雙擊的事件,并得到好友的編號.
		if(arg0.getClickCount()==2)   //getClickCount() 獲取鼠標被單機的次數(shù)
		{
			//得到該好友的編號 
			//getText() 的意思是:返回數(shù)據(jù)窗口控件中 懸浮在當前行列之上的
			String friendNum=((JLabel)arg0.getSource()).getText();
			
			//System.out.println("你希望和 "+friendNum+" 聊天");
			QqChat qqChat=new QqChat(owner,friendNum);  //傳入編號
		   Thread t=new Thread(qqChat);  
		   t.start();     // 啟動線程
		}
	}

	public void mousePressed(MouseEvent arg0) { //按下按鼠標鍵觸發(fā)的鼠標事件
		// TODO Auto-generated method stub
	}

	public void mouseReleased(MouseEvent arg0) {   //釋放鼠標鍵觸發(fā)的鼠標事件
		// TODO Auto-generated method stub		
	}
} 

//與好友聊天的界面
 //因為客戶端,要處于讀取的狀態(tài),因此我們把它做成一個線程
package com.qq.client.view;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import com.qq.common.*;
import com.qq.client.model.*;
public class QqChat extends JFrame implements ActionListener,Runnable{  //監(jiān)聽發(fā)送按鈕
	 Font font = new Font("宋體", Font.PLAIN, 20);                                          //實現(xiàn)Runnable接口實現(xiàn)多線程,
	JTextArea jta;    //文本域  存聊天內容
	JTextField jtf;    //文本框
	JButton jb;
	JPanel jp;
	String ownerId;
	String friendId;
	
	public QqChat(String owner,String friend)
	{ 
		ownerId= owner;
		friendId=friend;
		jta=new JTextArea();
		jtf=new JTextField(25);     //25個字符那么寬
		jb=new JButton("發(fā)送");
		jb.addActionListener(this);
		jb.setFont(font);
		jp=new JPanel();
		jp.add(jtf);
		jp.add(jb);	
		add(jta,"Center");
		add(jp,"South");
		setTitle(owner+"正在和 "+friend+" 聊天");  //設置標題
		setIconImage((new ImageIcon("image/qq.png").getImage())); //獲取圖像
		setLocation(800,400); //窗口的位置
		setSize(600, 500);
		setVisible(true);
	}
	
	//寫一個方法,讓它顯示消息
	public void showMessage(Message m)
	 {
		String info=m.getSender()+" 給"+m.getGetter()+" 發(fā)送:"+m.getCon()+"\r\n";
		this.jta.append(info);
	}
		
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub
		if(arg0.getSource()==jb)//如果用戶點擊了發(fā)送按鈕
		{
			Message m=new Message();
			m.setSender(this.ownerId);
			m.setGetter(this.friendId);
			m.setCon(jtf.getText());   //文本框中得到 
			  
			//發(fā)送給服務器  要拿到socket,可以把socket寫成靜態(tài)的,從類里面拿出來;
			try 
			{ 
				ObjectOutputStream oos=new ObjectOutputStream(QqClientConServer.s.getOutputStream());
				oos.writeObject(m);
			} 
			catch (Exception e) 
			{
				e.printStackTrace();
			}	
		}	
	}
	public void run()
	{
		while(true)
		{   //一直處于讀取狀態(tài)(如果讀不到就等待)
			try
			{
				ObjectInputStream ois=new ObjectInputStream(QqClientConServer.s.getInputStream());
				Message m =(Message)ois.readObject();		
				
				//顯示
				String info=m.getSender()+"給"+m.getGetter()+"發(fā)送"+m.getCon()+"\r\n";
			    this.jta.append(info);  //(添加)追加到文本域
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		
		}
	}
}

package com.qq.client.model;
import com.qq.common.*;
public class QqClientUser {
  
	  public boolean checkUser(User u)
	  {
		 return new QqClientConServer().sendLoginInfotoSSErver(u);
	  }
}

//客戶端鏈接服務器的部分
package com.qq.client.model;

import java.util.*;
import java.net.*;
import java.io.*;
import com.qq.common.*;
public class QqClientConServer{
    
	public static Socket s;
	
	//發(fā)送第一次請求,登錄請求
	public boolean sendLoginInfotoSSErver(Object o) //發(fā)送對象到服務器
	{  
		boolean b=false;
		try
		 { 
		     s=new Socket("127.0.0.1",9999);	 //傳入要連接主機與端口
			 ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream()); //輸出流
		     oos.writeObject(o);  //把o發(fā)出去
			 
		     ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
		     Message ms=(Message)ois.readObject();  
		     if(ms.getMesType().equals("1"))
		    	  b=true;
		 }
		 catch (Exception e)
		 {
			 e.printStackTrace();
		 }
		 finally
		 {
		 }
		return b;
	}
}

服務端代碼(message,user與客戶端一樣,這里不在寫出,直接復制過去就可以)文章來源地址http://www.zghlxwxcb.cn/news/detail-464763.html

//服務器端控制界面,可以完成啟動服務器,關閉服務器,可以管理和監(jiān)控用戶
package com.qq.server.view;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.qq.server.model.MyQqServer;
public class ControlPanel  extends JFrame implements ActionListener{
    
	JPanel jp1;
	JButton jstart,jend;

	public ControlPanel()
	{   Font font = new Font("宋體",Font.PLAIN,30);
	
		jp1=new JPanel();
		jstart=new JButton("啟動服務器");
		jstart.addActionListener(this);
		jend=new JButton("關閉服務器");
		jstart.setFont(font); jend.setFont(font);
		jstart.setForeground(Color.BLUE); jend.setForeground(Color.BLUE);
		
		jp1.add(jstart);
		jp1.add(jend);
		
		add(jp1);
		setLocation(150,150);
		setSize(900,900);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //結束窗口所在的應用程序  
		setVisible(true);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ControlPanel controlpanel =new ControlPanel();
	}
	
	public void actionPerformed(ActionEvent arg0)
	{
		if(arg0.getSource()==jstart)
		{
			new MyQqServer();
		}
	}
}

//qq服務器,監(jiān)聽,等待某個qq客戶端鏈接
package com.qq.server.model;

import java.io.*; //(I/O)流庫,提供大量的流類
import java.net.*;//導入網絡包
import java.util.*; //實用工具類,提供了一些實用的方法和數(shù)據(jù)結構
import com.qq.common.*;

public class MyQqServer  {

	public MyQqServer ()
	{
		//try-catch語句處理異常
        try
        { 
        	//ServerSocket類表示服務器socket
        	//在9999監(jiān)聽
    		System.out.println("服務器正在9999監(jiān)聽");//簡單判斷一下是否啟動服務端
        	ServerSocket ss=new ServerSocket(9999);
        while(true)   //服務器可多次監(jiān)聽
        {
            Socket s=ss.accept() ;  //阻塞,等待連接(與客戶端)
        	//接收客戶端發(fā)來的信息
           ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
            User u=(User)ois.readObject();
            System.out.println("用戶Id:"+u.getUserId()+"  密碼"+u.getPasswd()); 
          	Message m=new Message();
          	 ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
            if(u.getPasswd().equals("123456"))
            {
            	//返回一個成功登錄的信息
            	m.setMesType("1");    //mesType1 =1  表明登陸成功
                oos.writeObject(m); 
                
                //單開一個線程,讓該線程與該客戶端保持通信
                SerConClientThread scct=new SerConClientThread(s);
                ManageClientThread.addClientThread(u.getUserId(),scct);//放到HashMap
                scct.start(); //啟動與該客戶端通信的線程
            }
            else
            {
            	m.setMesType("2"); 
                oos.writeObject(m); 
                s.close();  //關閉連接(流)
            }
        }
       }
        catch(Exception e)
        {
        	e.printStackTrace();//將錯誤信息全部打印
        }
        finally{
        	
        }
	}
}
//服務器和某個客戶端的通信線程
package com.qq.server.model;

import java.net.*;
import java.io.*;
import com.qq.common.*;
public class SerConClientThread extends Thread    //繼承Thread類
{  
	Socket s;
	public SerConClientThread(Socket s)
	{
		this.s=s;  //把服務器和該客戶端的連接賦給s;
	}
	
    public void run()
    {
	   while(true)
	   {
		   //這里該線程就可以接受客戶端的信息
		   try
		   {
			     ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
			     Message m=(Message)ois.readObject();
			     
			     System.out.println(m.getSender()+"給 "+m.getGetter()+"發(fā)送: "+m.getCon());//判斷接受到客戶端的信息
		      
			     //拿到發(fā)送者與服務器的socket,此時就需要hashmap;
			     SerConClientThread sc=ManageClientThread.getClientThread(m.getGetter());
			     ObjectOutputStream oos=new ObjectOutputStream(sc.s.getOutputStream()); //接受人的通信線程;
		         oos.writeObject(m);
		   }
		   catch(Exception e)
		   {
			   e.printStackTrace();
		   }
	   }
   }
}

//管理客戶端線程
package com.qq.server.model;

import java.util.*;

public class ManageClientThread { 
  
	 public static HashMap hm=new HashMap<String, SerConClientThread>();
	  
	  //向hm中添加一個客戶通訊線程
	  public static void addClientThread(String uid,SerConClientThread ct)
	  {
		   hm.put(uid, ct);
	  }
	  
	  //返回socket
	  public static SerConClientThread getClientThread(String uid)
	  {
		  return (SerConClientThread) hm.get(uid);
	  }
	  
}

到了這里,關于java實現(xiàn)qq聊天(超詳細)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 基于java的聊天室系統(tǒng)設計與實現(xiàn)

    基于java的聊天室系統(tǒng)設計與實現(xiàn) 研究背景: 隨著互聯(lián)網技術的迅速發(fā)展和普及,在線聊天和實時通信成為人們日常交流的重要方式。聊天室系統(tǒng)作為實時通信的一種重要形式,具有廣泛的應用場景,如遠程教育、在線游戲、即時通訊、網絡直播等。因此,設計和實現(xiàn)一個基

    2024年02月05日
    瀏覽(21)
  • JAVA基于局域網的聊天室系統(tǒng)的設計與實現(xiàn)

    ? ? ? ?本文介紹了采用JAVA編程開發(fā)視頻聊天系統(tǒng)的一套比較常用的解決方案。文字聊天采用TCP模式;語音視頻聊天采用UDP模式,在客戶端之間點對點的進行。在該方案中,通過函數(shù)庫VFW來實現(xiàn)視頻捕獲、影像壓縮以及影像播放。微軟公司提供的專門用于視頻捕獲開發(fā)的工具

    2023年04月15日
    瀏覽(23)
  • 利用Java EE相關技術實現(xiàn)一個簡單的Web聊天室系統(tǒng)

    利用Java EE相關技術實現(xiàn)一個簡單的Web聊天室系統(tǒng)

    利用Java EE相關技術實現(xiàn)一個簡單的Web聊天室系統(tǒng) (1)編寫一個登錄頁面,登錄信息中有用戶名和密碼,分別用兩個按鈕來提交和重置登錄信息。 (2)通過請求指派來處理用戶提交的登錄信息,如果用戶名為本小組成員的名字且密碼為對應的學號時,跳轉到LoginSuccess顯示聊

    2024年02月07日
    瀏覽(33)
  • 純JAVA模擬、實現(xiàn)QQ簡易聊天互動程序

    純JAVA模擬、實現(xiàn)QQ簡易聊天互動程序

    實現(xiàn)的功能、步驟: 1、定義JFrame窗體中的組件 2、在構造方法中初始化窗體的組件 3、使用網絡編程完成數(shù)據(jù)的傳輸(TCP,UDP協(xié)議) 4、實現(xiàn)發(fā)送按鈕的監(jiān)聽點擊事件 5、實現(xiàn)回車鍵發(fā)送數(shù)據(jù)?? 功能演示: 沒有點發(fā)送,數(shù)據(jù)卻發(fā)送出去了是因為按了回車鍵? ?運用到的知識點

    2024年02月11日
    瀏覽(25)
  • 基于TCP協(xié)議的聊天室詳細教學(C++)

    基于TCP協(xié)議的聊天室詳細教學(C++)

    服務器只轉發(fā)消息不參到信息交流中 客戶端輸入用戶名后默認進入群聊模式,輸入“獲取用戶列表”可以獲取在線用戶用戶名列表,如果需要私聊某一個用戶需要輸入“私聊+用戶名”可進入私聊模式,輸入“退出私聊”可退出私聊重新進入群聊模式。 基本群聊展示 獲取用戶

    2024年02月08日
    瀏覽(23)
  • C語言Socket編程TCP簡單聊天室

    C語言Socket編程TCP簡單聊天室

    這是一個使用C語言進行套接字編程實現(xiàn)的簡單聊天室, 使用Pthread庫進行多線程執(zhí)行 服務端: svr.c 客戶端: cli.c Makefile: Makefile 執(zhí)行編譯 啟動服務器 啟動客戶端 聊天 退出

    2024年02月03日
    瀏覽(29)
  • Gin+WebSocket實戰(zhàn)——在線聊天室WebSocketDemo詳細使用教程

    Gin+WebSocket實戰(zhàn)——在線聊天室WebSocketDemo詳細使用教程

    Github:https://github.com/palp1tate/WebsocketDemo 歡迎star!?? 利用 Gin + WebSocket 實現(xiàn)的在線聊天室 Demo 項目,支持加入/離開聊天室廣播、給其他用戶發(fā)送消息等。 進入項目根目錄,執(zhí)行命令 go run . 命令,結果如下: 可以看到們的 HTTP 服務已經啟動成功并運行在了 8080 端口上。 接下

    2024年04月26日
    瀏覽(230)
  • Java 多人聊天室

    Java 多人聊天室

    Java實訓做的多人聊天室,效果如圖: 能夠實現(xiàn)多個客戶端之間的互相聊天,服務端來負責接收數(shù)據(jù)和轉發(fā)數(shù)據(jù)。 每個客戶端可以自己設置和修改自己的名稱,并傳給服務器讓其他客戶端知道。 當有客戶端加入和退出時,群聊里每個客戶端都有提示。(優(yōu)化了異常檢測,意外

    2024年02月10日
    瀏覽(21)
  • 【Java socket編程】多人聊天室

    【Java socket編程】多人聊天室

    課程設計大作業(yè) 功能: 1.具有 點對點通信 功能,任意客戶端之間能夠發(fā)送消息。 2.具有 群組通信 功能: 客戶端可以 自主建立群組 ,添加或刪除組成員; 客戶端能夠向組內成員同時發(fā)送消息,其他組成員不能收到。 3.具有 廣播 功能 客戶端能夠向所有其他成員 廣播消息

    2024年02月04日
    瀏覽(35)
  • SpringBoot與webSocket實現(xiàn)在線聊天室——實現(xiàn)私聊+群聊+聊天記錄保存

    SpringBoot與webSocket實現(xiàn)在線聊天室——實現(xiàn)私聊+群聊+聊天記錄保存

    引用參考:原文章地址:https://blog.csdn.net/qq_41463655/article/details/92410518 在此基礎上實現(xiàn)對聊天記錄的保存。 代碼地址:鏈接:https://pan.baidu.com/s/1IJFZDa4S_DF08773sKJWeA 提取碼:jkui 思路:新建一個實體類用于保存聊天記錄,在消息發(fā)送時,設置對象的各個值然后保存到數(shù)據(jù)庫中。

    2024年02月02日
    瀏覽(88)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包