前几日写的一篇简陋之极的java聊天室被各位前辈说是,一塌糊涂,乌烟瘴气,只是简单的实现了需要的功能,并未做到人性化。在下痛定思痛,心想还是先学会显示功能再做美化界面,美化代码的打算!
在奋斗了一天之后终于完成了集图片,文字,直线等功能为一体的群聊天室。先分析代码如下:
关于界面什么的我就不说了,笔者在前面的博客中有提过!直接附上各种功能的实现方法。
首先我们要传送信息,必须要让被传送的对象知道我们传送的是什么东西,所以在传送信息之前,我们首先要确定一个协议,比如说当客户端接收到的第一个int 值为1的时候,它接下来就要再接收4个int值,据此来画一条直线,而我服务器画一条直线的时候可以获得该直线的四个int值,但是在利用IO流发送这四个int值的时候,我首先要先发送一个1,也就是说我每次在要发送一天直线之前就要先发送一个1,当然在客户端读取的时候,我们第一次读取到的是1,就接收四个int。当读完四个int之后并画完一条直线之后我们还要读取数据,如果还是1的话,我们继续上面的操作,如果读取的是2,按照规定的协议,我们就调用相应的方法即可!!!!
现附上服务器发送直线的代码如下,该代码是写在界面类里面的内部类:
- //鼠标进入事件
- MouseListener ms=(new MouseListener(){
- public void mousePressed(MouseEvent e){
- x1=e.getX();
- y1=e.getY();
- }
- public void mouseReleased(MouseEvent e){
- int x2=e.getX();
- int y2=e.getY();
- g.drawLine(x1,y1,x2,y2);
- ChatTools.castbyte(1);
- ChatTools.castbyte(x1);
- ChatTools.castbyte(y1);
- ChatTools.castbyte(x2);
- ChatTools.castbyte(y2);
- }
- public void mouseClicked(MouseEvent e){}
- public void mouseEntered(MouseEvent e){}
- public void mouseExited (MouseEvent e){}
- });
- jp.addMouseListener(ms);
当然相应的我们也要在客户端定义一个读取数据的方法,首先我们要判断发送过来的是什么东西,我设置的协议是,如果首先读到的是1,接下来就画直线,如果读到的是2,接下来就接收一张图片,如果读到的是4,接下来读到的就是一段文字。该方法是放在客户端的线程中的,并且在线程的Run方法中调用该方法。
并且在每执行完一次操作之后,便再次读取一个int值,再次判断该int值为多少,以便得到下一个执行的指令。
- public void processServer(Socket client){
- try{
- ins=client.getInputStream();
- OutputStream out=client.getOutputStream();
- dis = new DataInputStream(ins);
- dout=new DataOutputStream(out);
- int t=dis.readInt();
- while(true){
- //如果读到的是1,调用读取线段的方法
- if(t==1){
- readline();
- }
- //读到的是2则调用接受画面的方法
- if(t==2){
- readPic();
- }
- //如果读到的是4,则调用接受文字的方法
- if(t==4){
- readMsg();
- }
- t=dis.readInt();
- }
- }catch(Exception ef){
- ef.printStackTrace();
- }
- }
当判断int值为1的时候,我们就调用画直线的方法,该方法如下
- //定义一个读取线段的方法
- public void readline() {
- try {
- int x1=dis.readInt();
- int y1=dis.readInt();
- int x2=dis.readInt();
- int y2=dis.readInt();
- g.drawLine(x1,y1,x2,y2);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
当然,我们需要在客户端和服务器都要定义相同功能的传送和接收方法。
现在我们再写一个文字的接收方法,首先我们会在文本输入框中输入字符,并获得该文本内容,每当按下发送这个按钮时便调用消息的传送方法,将该消息发送出去!
- ActionListener al=(new ActionListener(){
- public void actionPerformed(ActionEvent e){
- String s=e.getActionCommand();
- if(s.equals("创建")){
- Chatserver cs=new Chatserver(9090,jta,dout,g);
- cs.start();
- }
- //将服务器消息发给每个人
- if(s.equals("发送")){
- String msg=jte1.getText();
- ChatTools.castMsg(msg);
- jta.append("服务器说:"+msg+"\r\n");
- jte1.setText("");
- }
其中ChatTools.castMsg();是一个消息群发的方法,该方法在队列类里面定义的,代码如下
- //将一个消息发送给所有人
- ublic static void castMsg(String str){
- ChatTools.castbyte(4);
- for(int i=0;i<list.size();i++){
- ServerThread st=list.get(i);
- st.sendMs(i+"说:"+str);
- }
而sendMsg();则是一个消息的发送方法。该方法如下
- //将发送消息的代码包装到一个方法中
- public void sendMs(String msg){
- try{
- msg+="\r\n";
- dout.write(msg.getBytes());
- //强制输出
- dout.flush();
- }catch(Exception ef){}
- }
实现字符串传输的重中之重便是读取的方法,我们会首先获得一个为4的int值,然后我们就要调用字符串的读取方法
- public void readMsg(){
- try{
- brd=new BufferedReader(new InputStreamReader(ins));
- String input=brd.readLine();
- jta.append(input +"\r\n");
- }catch(Exception ef){}
- }
我使用的BufferedReader缓冲流,实现整行读取的方式,该方式不会产生乱码,所以还是不错的。
而我今天要重点讲的便是图片从文件中读取和传送的方法。
首先我们要获得图片,再者我们要获取图片的宽度和高度,在循环遍历每个像素点,获取该点的颜色值,接着我们便在画布中调用画线的方法,依次画出每个像素点,并相应的给每个点附上相应的颜色即可。这样一张图片就在自己的画布上显示出来了!代码如下
- ActionListener al=(new ActionListener(){
- public void actionPerformed(ActionEvent e){
- String s=e.getActionCommand();
- if(s.equals("创建")){
- Chatserver cs=new Chatserver(9090,jta,dout,g);
- cs.start();
- }
- //将服务器消息发给每个人
- if(s.equals("发送")){
- String msg=jte1.getText();
- ChatTools.castMsg(msg);
- jta.append("服务器说:"+msg+"\r\n");
- jte1.setText("");
- }
- if(s.equals("图片")){
- try {
- BufferedImage image = ImageIO.read(new File("2.jpg"));
- int m=image.getHeight();
- int n=image.getWidth();
- for(int i=0;i<n;i++){
- for(int j=0;j<m;j++){
- rgb=image.getRGB(i,j);
- System.out.println(i);
- System.out.println(j);
- Color color=new Color(rgb);
- g.setColor(color);
- g.drawLine(i,j,i,j);
- ChatTools.castbyte(2);
- ChatTools.castbyte(rgb);
- ChatTools.castbyte(i);
- ChatTools.castbyte(j);
- }
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- }
能画出图片,当然我们就能发送图片,我们就能相应的读取图片,在发送图片信息的时候,我们每取出一个点,就能获得该店的颜色,我们就把该点横坐标和纵坐标以及颜色值发送过去。在接收端,我们会首先读到一个为2的int值,然后程序会调用图片的读取方法。方法如下
- //图片的读取方法
- public void readPic(){
- int rgb;
- try {
- rgb = dis.readInt();
- int i=dis.readInt();
- int j=dis.readInt();
- Color color =new Color(rgb);
- g.setColor(color);
- g.drawLine(i,j,i,j);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
值此,我们就实现了图片的发送功能了。我的代码也差不多了,至于如果有什么需要改进的地方请各位多多指教,本人是新手,迫切渴望成长,我也知道我的代码可定有很多漏洞,望不吝赐教!!!!!!!!!!!
现在附上具体的代码:服务器的四个类
界面类
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseListener;
- import java.awt.image.BufferedImage;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.IOException;
- import javax.imageio.ImageIO;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- public class MainServer {
- private int x1;
- private int y1;
- private Graphics g;
- private DataOutputStream dout;
- private int rgb;
- public void ShowUI(){
- JFrame jf=new JFrame();
- jf.setTitle(" 服务器");
- jf.setSize(600,600);
- jf.setLayout(null);
- jf.setDefaultCloseOperation(3);
- JButton jb=new JButton("创建");
- jb.setBounds(0,0,60,30);
- final JButton jm = new JButton("图片");// 实例化菜单栏的对象
- jm.setBounds(70,0,60,30);
- jf.add(jm);
- JButton jb1=new JButton("发送");
- jb1.setBounds(0,40,60,30);
- final JTextField jte1=new JTextField(30);
- jte1.setBounds(70,45,300,20);
- final JTextArea jta=new JTextArea(20,30);
- jta.setBounds(0,80,600,150);
- final JPanel jp=new JPanel();
- jp.setBounds(0,250,600,600);
- jf.add(jb);
- jf.add(jb1);
- jf.add(jte1);
- jf.add(jta);
- jf.add(jp);
- jf.setVisible(true);
- jp.setBackground(Color.gray);
- this.g=jp.getGraphics();
- ActionListener al=(new ActionListener(){
- public void actionPerformed(ActionEvent e){
- String s=e.getActionCommand();
- if(s.equals("创建")){
- Chatserver cs=new Chatserver(9090,jta,dout,g);
- cs.start();
- }
- //将服务器消息发给每个人
- if(s.equals("发送")){
- String msg=jte1.getText();
- ChatTools.castMsg(msg);
- jta.append("服务器说:"+msg+"\r\n");
- jte1.setText("");
- }
- if(s.equals("图片")){
- try {
- BufferedImage image = ImageIO.read(new File("2.jpg"));
- int m=image.getHeight();
- int n=image.getWidth();
- for(int i=0;i<n;i++){
- for(int j=0;j<m;j++){
- rgb=image.getRGB(i,j);
- System.out.println(i);
- System.out.println(j);
- Color color=new Color(rgb);
- g.setColor(color);
- g.drawLine(i,j,i,j);
- ChatTools.castbyte(2);
- ChatTools.castbyte(rgb);
- ChatTools.castbyte(i);
- ChatTools.castbyte(j);
- }
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- }
- }
- });
- jm.addActionListener(al);
- jb.addActionListener(al);
- jb1.addActionListener(al);
- //鼠标进入事件
- MouseListener ms=(new MouseListener(){
- public void mousePressed(MouseEvent e){
- x1=e.getX();
- y1=e.getY();
- }
- public void mouseReleased(MouseEvent e){
- int x2=e.getX();
- int y2=e.getY();
- g.drawLine(x1,y1,x2,y2);
- ChatTools.castbyte(1);
- ChatTools.castbyte(x1);
- ChatTools.castbyte(y1);
- ChatTools.castbyte(x2);
- ChatTools.castbyte(y2);
- }
- public void mouseClicked(MouseEvent e){}
- public void mouseEntered(MouseEvent e){}
- public void mouseExited (MouseEvent e){}
- });
- jp.addMouseListener(ms);
- }
- public static void main(String[] args){
- MainServer ms=new MainServer();
- ms.ShowUI();
- }
- }
处理客户机连接的两个线程类
- import java.awt.Graphics;
- import java.io.DataOutputStream;
- import java.net.ServerSocket;
- import java.net.Socket;
- import javax.swing.JTextArea;
- public class Chatserver extends Thread{
- private Graphics g;
- private int port;
- private JTextArea jta;
- private DataOutputStream dout;//输出流
- private ServerSocket ss;
- public Chatserver(int port,JTextArea jta,DataOutputStream dout,Graphics g){
- this.port=port;
- this.jta=jta;
- this.dout=dout;
- this.g=g;
- }
- public void run(){
- setUpServer(port);
- }
- //在指定端口上创建一个服务器
- public void setUpServer(int port){
- try{
- ss = new ServerSocket(port);
- System.out.println("服务器创建成功");
- //等待客户机连接,并设置成循环等待状态
- while(true){
- Socket client=ss.accept();
- System.out.println("欢迎进入我的服务器");
- //启动一个线程去处理该对象
- ServerThread st=new ServerThread(client,jta,dout,g);
- st.start();
- ChatTools.add(st);
- ChatTools.castMsg("有人上线!!目前在线人数"+ChatTools.getsize());
- }
- }catch(Exception ef){
- ef.printStackTrace();
- }
- }
- }
- import java.awt.Color;
- import java.awt.Graphics;
- import java.io.BufferedReader;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.net.Socket;
- import javax.swing.JTextArea;
- public class ServerThread extends Thread{
- private Socket client;//线程中处理的客户对象
- private DataOutputStream dout;//输出流
- private OutputStream out;//输出流
- private DataInputStream dis;//
- private JTextArea jta;
- private BufferedReader brd;
- private InputStream ins;
- //创建线程对象时要传入他要处理的连接对象
- private Graphics g;
- public ServerThread(Socket client,JTextArea jta,DataOutputStream dout,Graphics g){
- this.client=client;
- this.jta=jta;
- this.dout=dout;
- this.g=g;
- }
- public void readMsg(){
- try{
- brd=new BufferedReader(new InputStreamReader(ins));
- String input=brd.readLine();
- jta.append("客户说:"+input +"\r\n");
- ChatTools.castMsg(input);
- }catch(Exception ef){}
- }
- //将发送消息的代码包装到一个方法中
- public void sendMs(String msg){
- try{
- msg+="\r\n";
- dout.write(msg.getBytes());
- //强制输出
- dout.flush();
- }catch(Exception ef){}
- }
- public void run(){
- //在线程中 调用处理链接的方法
- processChat(this.client);
- }
- //处理客户机进入的连接对象
- public void processChat(Socket client){
- try{
- ins=client.getInputStream();
- out=client.getOutputStream();
- dis = new DataInputStream(ins);
- dout=new DataOutputStream(out);
- int t=dis.readInt();
- while(true){
- if(t==1){
- readline();
- }
- if(t==2){
- readPic();
- }
- if(t==4){
- readMsg();
- }
- t=dis.readInt();
- }
- }catch(Exception ef){
- ef.printStackTrace();
- }
- }
- //发送int型值得方法
- public void sendbyte(int x1){
- try{
- dout.writeInt(x1);
- dout.flush();
- }catch(Exception e){}
- }
- //图片的读取方法
- public void readPic(){
- int rgb;
- try {
- rgb = dis.readInt();
- int i=dis.readInt();
- int j=dis.readInt();
- Color color =new Color(rgb);
- g.setColor(color);
- g.drawLine(i,j,i,j);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- //定义一个读取线段的方法
- public void readline() {
- try {
- int x1=dis.readInt();
- int y1=dis.readInt();
- int x2=dis.readInt();
- int y2=dis.readInt();
- g.drawLine(x1,y1,x2,y2);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
一个队列类,用来存储连接进服务器的客户机对象类
- import java.util.ArrayList;
- import java.util.List;
- public class ChatTools {
- //保存处理线程的队列对象
- static List<ServerThread> list=new ArrayList<ServerThread>();
- private ChatTools(){
- }//不需要创建引类对象,构造器则私有
- //取得保存保存处理线程对象的队列
- public static List<ServerThread> getAllthread(){
- return list;
- }
- //将一个客户对应的处理线程对象加入到队列中
- public static void add(ServerThread st){
- //通知有人上线了
- list.add(st);
- }
- public static int getsize(){
- int i=list.size();
- return i;
- }
- //将一个消息发送给所有人
- public static void castMsg(String str){
- ChatTools.castbyte(4);
- for(int i=0;i<list.size();i++){
- ServerThread st=list.get(i);
- st.sendMs(i+"说:"+str);
- }
- }
- //定义一个字节群发的方法
- public static void castbyte(int x1){
- for(int i=0;i<list.size();i++){
- ServerThread st=list.get(i);
- st.sendbyte(x1);
- }
- }
- }
接下来便是客户机的两个类
界面类
- package 多人聊天室客户端;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseListener;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import javax.imageio.ImageIO;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- public class Mainchat {
- private MainchatThread mt;
- private Graphics g;
- private int x1;
- private int y1;
- private InputStream ins;
- private int rgb;
- public void ShowUI(){
- JFrame jf=new JFrame();
- jf.setTitle(" 客户机");
- jf.setSize(600,500);
- jf.setLocation(700,0);
- jf.setLayout(null);
- jf.setDefaultCloseOperation(3);
- JButton jb=new JButton("连接");
- jb.setBounds(0,0,60,30);
- final JButton jm = new JButton("图片");// 实例化菜单栏的对象
- jm.setBounds(70,0,60,30);
- jf.add(jm);
- JButton jb1=new JButton("发送");
- jb1.setBounds(0,40,60,30);
- final JTextField jte1=new JTextField(30);
- jte1.setBounds(70,45,300,20);
- final JTextArea jta=new JTextArea(20,30);
- jta.setBounds(0,80,600,150);
- JPanel jp=new JPanel();
- jp.setBounds(0,250,600,400);
- jf.add(jb);
- jf.add(jb1);
- jf.add(jte1);
- jf.add(jta);
- jf.add(jp);
- jf.setVisible(true);
- jp.setBackground(Color.gray);
- this.g=jp.getGraphics();
- ActionListener al=(new ActionListener(){
- public void actionPerformed(ActionEvent e){
- String s=e.getActionCommand();
- if(s.equals("连接")){
- try {
- mt=new MainchatThread("localhost",9090,jta,g,ins);
- if(mt.runing()){
- mt.start();
- }
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- }
- //将消息发给别人
- if(s.equals("发送")){
- String msg=jte1.getText();
- jta.append("我说:"+msg+"\r\n");
- MainchatThread.sendbyte(4);
- mt.sendMsg(msg);
- System.out.println("消息已经发送");
- jte1.setText("");
- }
- if(s.equals("图片")){
- try {
- BufferedImage image = ImageIO.read(new File("2.jpg"));
- int m=image.getHeight();
- int n=image.getWidth();
- for(int i=0;i<n;i++){
- for(int j=0;j<m;j++){
- rgb=image.getRGB(i,j);
- System.out.println(i);
- System.out.println(j);
- Color color=new Color(rgb);
- g.setColor(color);
- g.drawLine(i,j,i,j);
- MainchatThread.sendbyte(2);
- MainchatThread.sendbyte(rgb);
- MainchatThread.sendbyte(i);
- MainchatThread.sendbyte(j);
- }
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- }
- }
- });
- jm.addActionListener(al);
- jb.addActionListener(al);
- jb1.addActionListener(al);
- jf.setVisible(true);
- MouseListener ms=(new MouseListener(){
- public void mousePressed(MouseEvent e){
- x1=e.getX();
- y1=e.getY();
- System.out.println(x1);
- }
- public void mouseReleased(MouseEvent e){
- int x2=e.getX();
- int y2=e.getY();
- g.drawLine(x1,y1,x2,y2);
- MainchatThread.sendbyte(1);
- MainchatThread.sendbyte(x1);
- MainchatThread.sendbyte(y1);
- MainchatThread.sendbyte(x2);
- MainchatThread.sendbyte(y2);
- }
- public void mouseClicked(MouseEvent e){}
- public void mouseEntered(MouseEvent e){}
- public void mouseExited (MouseEvent e){}
- });
- jp.addMouseListener(ms);
- }
- public static void main(String[] args){
- Mainchat ms=new Mainchat();
- ms.ShowUI();
- }
- }
线程类,用来运行客户机读取服务器发来的信息
- package 多人聊天室客户端;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.io.BufferedReader;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.net.Socket;
- import javax.swing.JTextArea;
- public class MainchatThread extends Thread{
- private static DataOutputStream dout;
- private InputStream ins;
- private BufferedReader brd;
- private int port;
- private String ip;
- private JTextArea jta;
- private Graphics g;
- private DataInputStream dis;
- private Socket socket;
- public MainchatThread(String ip,int port,JTextArea jta,Graphics g,InputStream ins){
- this.jta=jta;
- this.ip=ip;
- this.port=port;
- this.g=g;
- this.ins=ins;
- }
- public boolean runing(){
- try{
- socket=new Socket(this.ip,this.port);
- System.out.println("连接成功");
- InputStream ins=socket.getInputStream();
- OutputStream out=socket.getOutputStream();
- dis=new DataInputStream(ins);
- dout=new DataOutputStream(out);
- return true;
- }catch (Exception e){
- e.printStackTrace();
- }return false;
- }
- //图片的读取方法
- public void readPic(){
- int rgb;
- try {
- rgb = dis.readInt();
- int i=dis.readInt();
- int j=dis.readInt();
- Color color =new Color(rgb);
- g.setColor(color);
- g.drawLine(i,j,i,j);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- //发送信息
- public void sendMsg(String msg){
- try{
- msg+="\r\n";
- dout.write(msg.getBytes());
- dout.flush();
- }catch(Exception ef){}
- }
- public static void sendbyte(int i){
- try{
- dout.writeInt(i);
- dout.flush();
- }catch(Exception ef){}
- }
- //读取服务端信息的方法
- public void readMsg(){
- try{
- brd=new BufferedReader(new InputStreamReader(ins));
- String input=brd.readLine();
- jta.append(input +"\r\n");
- }catch(Exception ef){}
- }
- public void readline(){
- try{
- int x1=dis.readInt();
- int y1=dis.readInt();
- int x2=dis.readInt();
- int y2=dis.readInt();
- g.drawLine(x1,y1,x2,y2);
- }catch(Exception ef){}
- }
- public void processServer(Socket client){
- try{
- ins=client.getInputStream();
- OutputStream out=client.getOutputStream();
- dis = new DataInputStream(ins);
- dout=new DataOutputStream(out);
- int t=dis.readInt();
- while(true){
- //如果读到的是1,调用读取线段的方法
- if(t==1){
- readline();
- }
- //读到的是2则调用接收图片的方法
- if(t==2){
- readPic();
- }
- //如果读到的是4,则调用接受文字的方法
- if(t==4){
- readMsg();
- }
- t=dis.readInt();
- }
- }catch(Exception ef){
- ef.printStackTrace();
- }
- }
- public void run(){
- processServer(socket);
- }
- }
至此完结!!!