Java 聊天室的实现(非常具体)1

本文主要是复习一个我以前上课时写的小作业—java聊天室,当时刚接触Java不久,所以代码写的可能比较啰嗦。一步一步增加,一共写了13个版本。

如果你要看最终版本,点击Java 聊天室的实现(具体)2


第一个版本:这个版本的主要作用是利用socket是实现基本的客户端与服务器的连接。

// server.java
package Chat1;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	ServerSocket server;//做成全局变量
	//构造方法
	public Server() {
		System.out.println("正在启动服务器.....");
		try {
			server = new ServerSocket(8088);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//参数:端口号
		System.out.println("服务器已启动!");
	}
	
	//开始监听
	public void start() {
		System.out.println("正在等待客户端连接....");
		try {
			Socket socket = server.accept();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("客户端已连接!");
	}
	
	public static void main(String[] args) {
		Server server = new Server();
		server.start();
	}

}

//client.java
package Chat1;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	//构造方法
	public Client() {
		System.out.println("正在连接服务器........");
		try {
			Socket socket = new Socket("localhost",8088);//两个参数,一个是服务器的IP地址,一个是服务器的端口号;写完之后对异常进行处理(try..catch)
		} catch (UnknownHostException e) {//UnknownHostException e:未知服务器异常
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {//IOException e:未知IO流异常,因为Socket是通过信息流来传递的,所以得捕获异常
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("服务器已连接!");
	}
	
	public static void main(String[] args) {
		Client client = new Client();
	}
}

运行程序时先启动服务端,再启动客户端。
当服务端启动成功时,服务端会显示:“正在启动服务器…服务器已启动!正在等待客户端连接…”,当客户端已经连接上时,服务端会显示“客户端已连接”


第二个版本:这个版本的主要作用是利用Frame类实现图形界面的编写。

//client.c
package Chat2;

import java.awt.*;//Frame

public class Client extends Frame{//继承框架
	
	public static void main(String[] args) {
		new Client().launchFrame();
		
	}
	
	//窗口框架
	public void launchFrame() {
		setLocation(800,300);//控制窗口位置
		this.setSize(400,400);//控制窗口大小
		setVisible(true);
	}
}

第三个版本:这个版本的主要作用是完善图形界面,加入输入框与显示框。

package Chat3;

import java.awt.*;//Frame
//加上输入输出创口
public class Client extends Frame{//继承框架
	
	TextField tfText = new TextField();//全局变量,方便后面使用
	TextArea taContext = new TextArea();
	
	public static void main(String[] args) {
		new Client().launchFrame();
		
	}
	
	public void launchFrame() {
		setLocation(800,300);//位置
		this.setSize(400,400);//大小
		add(tfText,BorderLayout.SOUTH);//显示框加到南边
		add(taContext,BorderLayout.NORTH);//输入框加到北边
		pack();//处理中间大部分空白
		setVisible(true);
	}
}

第四个版本:这个版本的主要作用是完善图形界面,定义窗口关闭按钮。细心的朋友可能会发现上一个版本的窗口不能点关闭按钮关闭,我们这一版本就是解决这个问题。

package Chat4;

import java.awt.*;//Frame
import java.awt.event.*;//WindowAdapter,WindowEvent

//定义关掉窗口
public class Client extends Frame {// 继承框架

	TextField tfText = new TextField();// 全局变量,方便后面使用
	TextArea taContext = new TextArea();

	public static void main(String[] args) { 
		new Client().launchFrame();

	}

	public void launchFrame() {
		setLocation(800, 300);// 位置
		this.setSize(400, 400);// 大小
		add(tfText, BorderLayout.SOUTH);// 显示框加到南边
		add(taContext, BorderLayout.NORTH);// 输入框加到北边
		pack();// 处理中间大部分空白
		this.addWindowListener(new WindowAdapter() {//匿名类WindowAdapter是个抽象类,里面对接口WindowListener的方法都进行了空实现。			这样编程时不需要自己再去实现全部接口WindowListener里的方法。只需覆写自己需要的方法,其他的方法			WindowAdapter都实现了

			@Override
			//重写windowsClosing
			public void windowClosing(WindowEvent arg0) {
				System.exit(0);//正常退出就行
			}
			
		});
		setVisible(true);
	}

}


第5个版本:这个版本的主要作用是完善图形界面,把输入框里面的内容通过Enter显示到输出框中

package Chat5;

import java.awt.*;//Frame
import java.awt.event.*;//WindowAdapter,WindowEvent

//把tfText里面的内容通过Enter进入到taContext
public class Client extends Frame {// 继承框架

	TextField tfText = new TextField();// 全局变量,方便后面使用
	TextArea taContext = new TextArea();

	public static void main(String[] args) { 
		new Client().launchFrame();
	}
	
	//窗口
	public void launchFrame() {
		setLocation(800, 300);// 位置
		this.setSize(400, 400);// 大小
		add(tfText, BorderLayout.SOUTH);// 显示框加到南边
		add(taContext, BorderLayout.NORTH);// 输入框加到北边
		pack();// 处理中间大部分空白
		this.addWindowListener(new WindowAdapter() {//WindowAdapter是个抽象类,里面对接口WindowListener的方法都进行了空实现。			这样编程时不需要自己再去实现全部接口WindowListener里的方法。只需覆写自己需要的方法,其他的方法			WindowAdapter都实现了
			@Override
			//重写windowsClosing
			public void windowClosing(WindowEvent arg0) {
				System.exit(0);//正常退出就行
			}
			
		});
		tfText.addActionListener(new TFListener());
		setVisible(true);
	}

	//把tfText里面的内容通过Enter进入到taContext
	private class TFListener implements ActionListener{

		public void actionPerformed(ActionEvent e) {
			String s = tfText.getText().trim();//trim去掉空格
			taContext.setText(s);
			tfText.setText("");//处理enter后的tfText,使其为空。
		}
		
	}
}


第6个版本:这个版本的主要作用重新写了一下服务器,主要是加入了一个死循环来进行与客户端的连接,这么做的原因有二:1.为了方面进行一个服务端与多个客户端连接,2.为了解决一次连接失败的问题。

package Chat6;

import java.io.IOException;
import java.net.*; 

public class Server {
	
	public static void main(String[] args) {
		try {
			ServerSocket sc = new ServerSocket(8088);
			//接受客户端连接,不一定是一个连接,就用死循环
			while(true) {
				Socket s = sc.accept();
System.out.println("a client connected!");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


第7个版本:这个版本的主要作用实现已经有窗口的客户端与服务器的连接。

//client.java
package Chat7;

import java.net.*;
import java.awt.*;//Frame
import java.awt.event.*;//WindowAdapter,WindowEvent
import java.io.IOException;

//与Server连接
public class Client extends Frame {// 继承框架

	TextField tfText = new TextField();// 全局变量,方便后面使用
	TextArea taContext = new TextArea();

	public static void main(String[] args) { 
		new Client().launchFrame();
	}
	
	//Connet,与客户端进行连接
	public void connect() {
		try {
			Socket s = new Socket("localhost",8088);//127.0.0.1
System.out.println("connected!");
		} catch (UnknownHostException e) {//找不到主机
			e.printStackTrace();
		} catch (IOException e) {//网卡上有错
			e.printStackTrace();
		}
	}
	
	//窗口
	public void launchFrame() {
		setLocation(800, 300);// 位置
		this.setSize(400, 400);// 大小
		add(tfText, BorderLayout.SOUTH);// 显示框加到南边
		add(taContext, BorderLayout.NORTH);// 输入框加到北边
		pack();// 处理中间大部分空白
		this.addWindowListener(new WindowAdapter() {//WindowAdapter是个抽象类,里面对接口WindowListener的方法都进行了空实现。			这样编程时不需要自己再去实现全部接口WindowListener里的方法。只需覆写自己需要的方法,其他的方法			WindowAdapter都实现了
			@Override
			//重写windowsClosing
			public void windowClosing(WindowEvent arg0) {
				System.exit(0);//正常退出就行
			}
			
		});
		tfText.addActionListener(new TFListener());
		setVisible(true);
		connect();//发完信息后直接连接
	}

	//把tfText里面的内容通过Enter进入到taContext
	private class TFListener implements ActionListener{

		public void actionPerformed(ActionEvent e) {
			String s = tfText.getText().trim();//trim去掉空格
			taContext.setText(s);
			tfText.setText("");//处理enter后的tfText,使其为空。
		}
		
	}
}


第8个版本:这个版本的主要作用实现将客户端输入的内容发送到服务器。主要改变有两处:1.是在服务端要加入输入函数InputStream 2.是在客户端加入输出函数OutputStream

//server.java
package Chat8;

import java.io.*;
import java.io.IOException;
import java.net.*; 

public class Server {
	
	public static void main(String[] args) {
		try {
			ServerSocket sc = new ServerSocket(8088);
			//接受客户端连接,不一定是一个连接,就用死循环
			while(true) {
				Socket s = sc.accept();
System.out.println("a client connected!");
				DataInputStream dis = new DataInputStream(s.getInputStream());
				String str = dis.readUTF();//readUTF是转化成utf-8编码格式的
				System.out.println(str);
				dis.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


//client.java
package Chat8;

import java.io.*;
import java.net.*;
import java.awt.*;//Frame
import java.awt.event.*;//WindowAdapter,WindowEvent
import java.io.IOException;

//把输入的内容发送过去
public class Client extends Frame {// 继承框架

	Socket s = null;
	TextField tfText = new TextField();// 全局变量,方便后面使用
	TextArea taContext = new TextArea();

	public static void main(String[] args) { 
		new Client().launchFrame();
	}
	
	//Connet
	public void connect() {
		try {
			s = new Socket("localhost",8088);//127.0.0.1
System.out.println("connected!");
		} catch (UnknownHostException e) {//找不到主机
			e.printStackTrace();
		} catch (IOException e) {//网卡上有错
			e.printStackTrace();
		}
	}
	
	//窗口
	public void launchFrame() {
		setLocation(800, 300);// 位置
		this.setSize(400, 400);// 大小
		add(tfText, BorderLayout.SOUTH);// 显示框加到南边
		add(taContext, BorderLayout.NORTH);// 输入框加到北边
		pack();// 处理中间大部分空白
		this.addWindowListener(new WindowAdapter() {//WindowAdapter是个抽象类,里面对接口WindowListener的方法都进行了空实现。			这样编程时不需要自己再去实现全部接口WindowListener里的方法。只需覆写自己需要的方法,其他的方法			WindowAdapter都实现了
			@Override
			//重写windowsClosing
			public void windowClosing(WindowEvent arg0) {
				System.exit(0);//正常退出就行
			}
			
		});
		tfText.addActionListener(new TFListener());
		setVisible(true);
		connect();//发完信息后直接连接
	}

	//把tfText里面的内容通过Enter进入到taContext
	private class TFListener implements ActionListener{
		//处理enter以后的动作,我们现在想enter后把输入的东西发过去,得在这里进行处理。
		public void actionPerformed(ActionEvent e) {
			String str = tfText.getText().trim();//trim去掉空格
			//把输入的展示到展示框中。
			taContext.setText(str);
			tfText.setText("");//处理enter后的tfText,使其为空。
			//把输入的内容发送到Server中
			SendMessage(str);
		}
	}
	//把输入的内容发送到Server中
	public void SendMessage(String str) {
		try {
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());//DataOutputStream:数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后应用程序可以使用数据输入流将数据
			dos.writeUTF(str);//发送消息
			dos.flush();//你向输出流写入东西之后,执行flush(),目的是把缓冲区里的东西强行写入输出流.因为有些带缓冲区的输出流要缓冲区满的时候才输出.
			dos.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	
}


写到这里,文档开始变得卡起来来了,所以我决定分为两篇写完吧。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值