简单的的多人聊天端_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 简单的的多人聊天端

简单的的多人聊天端

 2013/7/31 1:09:10  不平凡的人  程序员俱乐部  我要评论(0)
  • 摘要:packagecgh20130727分部实现多人通信;importjava.io.IOException;importjavax.swing.JTextArea;/***定义一个TestServer的类创建一个服务器*@authorAllen**/publicclassTestServerextendsThread{privateintport;privateJTextAreajta;//构造方法进行参数的传递publicTestServer(intport,JTextAreajta)
  • 标签:
class="java" name="code">package cgh20130727分部实现多人通信;

import java.io.IOException;

import javax.swing.JTextArea;

/**
 * 定义一个TestServer的类创建一个服务器
 * @author Allen
 *
 */
public class TestServer extends Thread {

	private int port;
	private JTextArea jta;
	
	//构造方法进行参数的传递
	public TestServer(int port,JTextArea jta){
		this.port = port;
		this.jta = jta;
	}
	//空参数构造方法
    public TestServer() {
		
	}
    
    //重写run方法
    public void run(){
    	
    server(port);
    }


	//定义一个创建一个服务器的方法
	public void server(int port){
	
		try {
			
			//创建服务器
			java.net.ServerSocket server = new java.net.ServerSocket(port);
			System.out.println("你的服务器创建成功了!!!\r\n"+"端口号: "+port);
			
			while(true){
				
			//阻塞等待客户端的连接
			java.net.Socket soclicent = server.accept();
		    //创建一个多线程对象
			ServerThread sth = new ServerThread(soclicent,jta);
			sth.start();//线程开始运行
			chatList.add(sth);
			}
			
		} catch (IOException e) {
		  e.printStackTrace();
		}
	}
	
}

?创建一个服务器代码就那么三行,比较固定看看书也就搞定了.但在程序运行的时候遇到了一个bug,就是在已有的界面上(服务器界面)显示的时候点击"端口"按钮创建服务器对象的时候一直处于运行状态,最后知道了原来是没有添加线程的原因.

?

package cgh20130727分部实现多人通信;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.JTextArea;

import cgh20130728多人聊天客户端.customListe;

/**
 * 定义一个客户端对象继承自多线程
 * @author Allen
 *
 */
public class ServerThread extends Thread {

	private java.net.Socket soclicent;//定义一个客户端的属性
	private java.io.InputStream ins;
	private java.io.OutputStream ous;
	private String ip;
	private int port;
	private JTextArea jta;
	
    //构造方法进行参数的传递
	public ServerThread(java.net.Socket soclicent,JTextArea jta){
		this.soclicent = soclicent;
		this.jta = jta;
	}
	
	public ServerThread(String ip,int port,JTextArea jta){
		this.ip = ip;
		this.port = port;
		this.jta = jta;
	}
	
	//重写线程run的方法
	public void run(){
		work(this.soclicent);
	}
	
	//定义从客户端连接到服务器的方法
	public void work(java.net.Socket soclicent){
		
		try {
			//客户端接收输入输出流
			ins = soclicent.getInputStream();
			ous = soclicent.getOutputStream();
			
			//验证是否连接成功
			String str = "hello,welcome to Lanjie!!!"+"\r\n";
			byte [] bytes = str.getBytes();
			ous.write(bytes);
			ous.flush();
			
	        //将字符串读到服务器
		    String strRead = readString(ins);
		    //判断当读到exit时停止
		    while(!strRead.equals("exit")){
				System.out.println("服务器接收到的内容是++++\r\n"+strRead);
				String sing = "客户端保存的内容是----\r\n"+strRead;
			    byte [] by = sing.getBytes();
//			    ous.write(by);
//			    ous.flush();//强制刷新
				chatList.sendMsg(by);//客户端接收到的消息
				jta.setText(strRead);//将客户端接收到的消息显示在文本框中
			    strRead = readString(ins);//下一次得到的字符串
			   
		    }
		    }catch (IOException e) {
				
				e.printStackTrace();
			}
			
		
		}

    //定义一个读入字符串的方法
	public String readString(java.io.InputStream ins){
		
		//创建一个字符串缓冲器对象
		StringBuffer strb = new StringBuffer();
		
		int reads = 0;
		
		//判断当读到回车是停止字符的存入
		while(reads != 35){
			try {
				reads = ins.read();//将字符读入到服务器
				strb.append((char)reads);//将读到的字符放入字符串缓冲区
				
			} catch (IOException e) {
				
				e.printStackTrace();
			}
		}
		String sting = strb.toString().trim();//将缓冲区的字符整合成字符串
		
		return sting;
	}
	//定义一个服务器发送消息的方法
	public void writeMsg(byte [] by){
		
		try {
			System.out.println("writeMsg执行了");
			ous.write(by);
			ous.flush();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
	}

}

?写该类的时候遇到的一个是:当在程序运行的时候,不管是服务器的界面文本框还是客户端的文本框一直没有显示,纠结了半天最后终于找到原来是没有写该条指令jta.setText(strRead);

?

?

?

package cgh20130727分部实现多人通信;

import java.util.ArrayList;
import java.util.List;

/**
 * 定义一个chatList的队列类用来存储客户端对象
 * @author Allen
 *
 */
public class chatList {

	//定义一个私有的构造方法
    private chatList(){
    	
    }
    
    //调用系统提供的数组队列
	public static List<ServerThread> list = new ArrayList<ServerThread>();
	
	//定义一个数组队列的添加方法
	public static void add(ServerThread sth){
		list.add(sth);
		
	}
	
	//定义一个发送消息的方法
	public static void sendMsg(byte [] by){
		System.out.println("sendMsg执行了");
		//循环遍历数组队列
		for(int i=0;i<list.size();i++){
			ServerThread st = list.get(i);
			st.writeMsg(by);
		}
	}
}

?该类主要是实现将ServerThread保存数组队列中,然后调用sendMsg(by);方法实现客户端与客户端之间,客户端与服务器之间互相发送消息.

?

?

?

package cgh20130727分部实现多人通信;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * 创建一个服务器界面类
 * @author Allen
 *
 */
public class ServerUI extends JFrame{

	private JTextArea jta;
	private TestServer tse;
	private int nport;
	/**
	 * 定义一个程序的入口主函数
	 * @param args
	 */
	public static void main(String[] args) {
		//创建一个对象并调用窗体初始化的方法
		ServerUI sui = new ServerUI();
		sui.INtUI();

	}

	//定义一个窗体初始化的方法
	public void INtUI() {
		this.setTitle("服务器");
		this.setSize(400,300);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		//设置窗体的流式布局
		this.setLayout(new FlowLayout());
		//创建按钮对象
		JButton jbu = new JButton("端口");
		JButton jbu1 = new JButton("发送");
		//创建文本框对象
		final JTextField jte = new JTextField(25);
		final JTextField jte1 = new JTextField(25);
		//创建一个纯文本多行区域
		jta = new JTextArea(); 
		jta.setPreferredSize(new Dimension(350,180));
		 //添加到窗体
		 this.add(jbu);
		 this.add(jte);
		 this.add(jbu1);
		 this.add(jte1);
		 this.add(jta);
		 
		 //创建监听器
		 ActionListener action = new ActionListener(){

			//调用事件监听器的方法 
			public void actionPerformed(ActionEvent e) {
			
				if(e.getActionCommand().equals("端口")){
					nport = Integer.parseInt(jte.getText());
				
					tse = new TestServer(nport,jta);//创建客户端对象
					tse.start();//调用连接服务器的方法
					System.out.println("------>"+nport);
				}
				
				if(e.getActionCommand().equals("发送")){
					//从文本框得到消息
					String info = jte1.getText();
					//服务器将消息发送给每个客户端
					chatList.sendMsg(info.getBytes());
					//服务器的文本区域得到文本
					jta.append("fuwuqi : \r\n"+info);
					//发送完毕后清空文本框
					jte1.setText("");
					System.out.println("服务器发送消息给客户端成功"+info);
				}
				
			}
			
		 };
		 jbu.addActionListener(action);
		 jbu1.addActionListener(action);//按钮添加监听器
		//设置窗体可见性
		this.setVisible(true);
	}

}

该类主要是写一个服务器的界面并实现创建服务器,群发消息的方法

?

package cgh20130727分部实现多人通信1;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import cgh20130727分部实现多人通信.ServerThread;
import cgh20130727分部实现多人通信.chatList;

/**
 * 创建一个客户端的界面继承自JFrame
 * @author Allen
 *
 */
public class KehuduanUI extends JFrame {

	private JTextArea jta;
	private KehuWay khw;
	/**
	 * 程序的入口主函数
	 * @param args
	 */
	public static void main(String[] args) {
	   //实例化一个对象并调用窗体初始化的方法
		KehuduanUI khd= new KehuduanUI();
		khd.INtUI();
	}

	//初始化一个界面的方法
	public void INtUI() {
		
		this.setTitle("客户端");
		this.setSize(400,300);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		//设置窗体的流式布局
		this.setLayout(new FlowLayout());
		//创建按钮对象
		JButton jbu = new JButton("连接");
		JButton jbu1 = new JButton("群聊");
		//创建文本框对象
	    JTextField jte = new JTextField(25);
		final JTextField jte1 = new JTextField(25);
		//创建一个纯文本多行区域
		jta = new JTextArea(); 
		jta.setPreferredSize(new Dimension(350,180));
		 //添加到窗体
		 this.add(jbu);
		 this.add(jte);
		 this.add(jbu1);
		 this.add(jte1);
		 this.add(jta);
		 
		 //创建监听器
		 ActionListener action = new ActionListener(){

			//调用监听器的方法 
			public void actionPerformed(ActionEvent e) {
			
				if(e.getActionCommand().equals("连接")){
				
					khw = new KehuWay("localhost",9007,jta);//创建一个客户端对象
					//判断客户端是否创建成功
					if(khw.connectServer()){
						khw.start();
					}
				}
				
				if(e.getActionCommand().equals("群聊")){
				    String stri = jte1.getText();
					jta.append("kehuduan : \r\n"+stri+"\r\n");
					khw.sendInfo(stri);
					jte1.setText("");//发完后清空文本框
					
				}
				
			}
			 
		 };
		 //添加监听器
		 jbu.addActionListener(action);
		 jbu1.addActionListener(action);
		 
	     //显示窗体的可见性
		 this.setVisible(true);
		
	}

}

?有了客户端界面就需要有一个服务器的界面.

?

package cgh20130727分部实现多人通信1;

import java.io.BufferedReader;
import java.io.IOException;

import javax.swing.JTextArea;

import cgh20130727分部实现多人通信.chatList;

/**
 * 定义客户端方法的类继承自多线程
 * @author Allen
 *
 */
public class KehuWay extends Thread {
	
	private String ip;
	private int port;
	private java.io.OutputStream ous;
	private java.io.InputStream ins;
	private BufferedReader bufr;
	private JTextArea jta;
	private String sting;
	private String string = null;
	
	//构造方法进行参数的传递
	public KehuWay(String ip,int port,JTextArea jta){
		this.ip = ip;
		this.port = port;
		this.jta = jta;
	}

	//判断客户端是否与服务器连接成功
	public boolean connectServer(){
		
		try {
			//创建连接服务器的对象
			java.net.Socket client = new java.net.Socket(ip,port);
			System.out.println("客户端与服务器连接成功了!!!");
			//获取输入输出流
			ins = client.getInputStream();
			ous = client.getOutputStream();
			System.out.println("----++++");
			return true;
		
		} catch (IOException e) {
		e.printStackTrace();
		}
		return false;
	}
	//客户端发送消息
	public void sendInfo(String info){
		
		try {
			
			//info+="\r\n";
			ous.write(info.getBytes());
			ous.flush();//强制刷新
			
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
    }
	//客户端接收消息的方法
	public void readInfo(){
		
     System.out.println("readInfo执行了!");
   		
   		while(true){
   		  //创建一个字符串缓冲器对象
   	   		StringBuffer strb = new StringBuffer();
   	   		int reads = 0;
   	   		//判断当读到回车是#字符的存入
   	   		while(reads != 35){
   	   			try {
   	   				reads = ins.read();//将字符读入到服务器
   	   				strb.append((char)reads);//将读到的字符放入字符串缓冲区
   	   				
   	   			} catch (IOException e) {
   	   				e.printStackTrace();
   	   			}
   	   		}
//   	   		System.out.println("while(reads != 13)循环退出了");
   	   		sting = strb.toString().trim();//将缓冲区的字符整合成字符串
   	   		System.out.println("客户端接收到的消息是: "+sting);
   	   		jta.setText(sting);
   	   		if(sting == "exit"){
   	   			break;
   	   		}
   		}
   		System.out.println("readInfo结束!");

    }
	//重写run方法
	public void run(){
		System.out.println("客户端的run方法执行了");
		readInfo();
		System.out.println("客户端的run方法结束了");
	}
	
}

?写该类遇到的一个问题就是,当执行readInfo();方法的时候,少些了while(true){}的一个死循环.当没有该循环的时候读入的方法只是执行一次当读到#的时候程序结束了readInfo(),同时也就结束了run();方法跳出了线程,这之后读不到了消息

?

?

上一篇: 最近经常使用java的反射,发现一些反射的弊端 下一篇: 没有下一篇了!
  • 相关文章
发表评论
用户名: 匿名