简单实现本地QQ聊天器(最简单版本)

来源:互联网 发布:knockout.js 编辑:程序博客网 时间:2024/05/16 18:46
之前老师为了讲"socket"套接字,讲了一遍如何实现一个简单版本的QQ聊天器,今天复习了一遍,觉得有些地方的知识点还是没有掌握的很好,于是来一篇博客压压惊

先简单介绍一下”socket”套接字:

 在客户/服务器通信模式中, 客户端需要主动创建与服务器连接的 Socket(套接字), 服务器端收到了客户端的连接请求, 也会创建与客户连接的 Socket. Socket可看做是通信连接两端的收发器, 服务器与客户端都通过 Socket 来收发数据. 一句话蔽之就是"socket"就是客户端和服务器端之间的联通管道,任何信息的收发都是通过"socket"套接字来实现的

介绍完了”socket”套接字的概念,就来简单介绍一下实现”socket”的代码

客户端:import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class TestClient {    public static void main(String[] args) {        try {            Socket socket = new Socket("127.0.0.1",9999);            OutputStream os = socket.getOutputStream();            os.write(2);            InputStream is = socket.getInputStream();            System.out.println("server:"+is.read());        } catch (Exception e) {        }    }}服务器端package SocketPractice;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class TestServer {    public static void main(String[] args) {        try {            //创建一个服务器套接字对象 并绑定到特定端口号            ServerSocket server = new ServerSocket(9999);            //获取连接的客户端对象            //如果没有连接的对象 此处将堵塞            Socket socket = server.accept();            OutputStream os = socket.getOutputStream();            os.write(1);            InputStream is = socket.getInputStream();            System.out.println("client:"+is.read());        } catch (Exception e) {            e.printStackTrace();        }    }}/*其中的ServerSocket server = new ServerSocket(9999);9999表示端口号Socket socket = new Socket("127.0.0.1",9999);"127.0.0.1"表示服务端的地址若想要获得连接,端口号和服务端地址都不能有差错当连接成功后,就可以通过socket对象进行数据的传输了/*

现在进入正题,介绍一下简单本地QQ聊天器的实现
先上一个效果图
这里写图片描述

现在上代码
- QQ的客户端

package SocketPractice;import java.awt.BorderLayout;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;import java.net.UnknownHostException;import javax.swing.*;public class QQClient extends JFrame {    public QQClient(){        //上面部分的的聊天框        JTextArea jta = new JTextArea();        JScrollPane jsp = new JScrollPane(jta);        jta.setEditable(false);        //下面部分的输入框        JPanel jp = new JPanel();        JButton send = new JButton("发送");        JTextField jtf = new JTextField(20);        jp.add(send);        jp.add(jtf);        this.add(jp,BorderLayout.SOUTH);        this.add(jsp);        //基本设置        this.setSize(500,550);        this.setTitle("Client");        this.setVisible(true);        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        try {            Socket socket = new Socket("127.0.0.1",9999);            InputStream is = socket.getInputStream();            OutputStream os = socket.getOutputStream();            send.addActionListener(new SendClientListener(jtf, jta, os));            InputStreamReader isr = new InputStreamReader(is);            BufferedReader br = new BufferedReader(isr);            String msg = null;            while((msg = br.readLine())!=null){                jta.append("server:"+msg+"\r\n");            }        } catch (Exception e) {            e.printStackTrace();        }    }    public static void main(String[] args) {        new QQClient();    }}
  • 客户端send按钮的监听器
package SocketPractice;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.OutputStream;import java.io.PrintWriter;import javax.swing.*;public class SendClientListener implements ActionListener {    private JTextField jtf ;    private JTextArea jta;    private OutputStream os;    public SendClientListener(JTextField jtf,JTextArea jta,OutputStream os){        this.jtf = jtf;        this.jta = jta;        this.os = os;    }    public void actionPerformed(ActionEvent e){        String msg = jtf.getText();        jtf.setText("");        jta.append("Client"+msg+"\r\n");        PrintWriter pw = new PrintWriter(os,true);        pw.println(msg);    }}
  • QQ的服务器端
package SocketPractice;import java.awt.BorderLayout;import java.awt.event.ActionListener;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.*;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import org.xml.sax.InputSource;public class QQserver extends JFrame {    public QQserver(){        //下面部分        JPanel jp = new JPanel();        JButton send = new JButton("发送");        JTextField jtf = new JTextField(20);        jp.add(send);        jp.add(jtf);        this.add(jp,BorderLayout.SOUTH);        //下面部分        JTextArea jta = new JTextArea();        jta.setEditable(false);        JScrollPane jsp = new JScrollPane(jta);        this.add(jsp);        this.setSize(550,500);        this.setVisible(true);        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        this.setTitle("server");        try {            ServerSocket server = new ServerSocket(9999);            Socket socket = server.accept();            OutputStream os = socket.getOutputStream();            send.addActionListener(new SendServerListener(jtf, jta, os));            InputStream is = socket.getInputStream();            InputStreamReader isr = new InputStreamReader(is);            BufferedReader br = new BufferedReader(isr);            String msg = null;            while((msg = br.readLine())!=null){                jta.append("Client:"+msg+"\r\n");            }        } catch (IOException e) {            e.printStackTrace();        }    }    public static void main(String[] args) {        new QQserver();    }}
  • 服务器端send按钮的监听器
package SocketPractice;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.OutputStream;import java.io.PrintStream;import java.io.PrintWriter;import javax.swing.*;public class SendServerListener implements ActionListener {    private JTextField jtf;    private JTextArea jta;    OutputStream os;    public SendServerListener(JTextField jtf,JTextArea jta,OutputStream os ){        this.jtf = jtf;        this.jta = jta;        this.os = os;    }    public void actionPerformed(ActionEvent e){        //从输入框将文本获取        String msg = jtf.getText();        //清空        jtf.setText("");        //将文本输送到聊天框内        jta.append("server"+msg+"\r\n") ;        //true代表着自动刷新        PrintWriter pw = new PrintWriter(os,true);        pw.println(msg);    }}

以上就是全部代码,现在我要总结一下做QQ聊天器中我犯的一些问题

  1. 任何的监听器,都应该实现”ActionListener”这个接口,否则在面板中添加监听器时,会出现实参不匹配,要求增加cast强制类型转换的报错提示

  2. 在监听器的代码中”actionPerformed”的方法中,含有”PrintWriter”流,这个流负责着向另一端的socket输出文本的任务,既然是一个输出流,就会有着刷新的责任,所以可以这样做,自动的刷新流.

PrintWriter pw = new PrintWriter(os,true);

如若不然,就会出现文本停留到流中,而不会传送到在另一端的现象.

3.当涉及到纯文本传输的时候,可以考虑先用”InputStream”流来建立字节流,再用”InputStreamReader”流来修饰原来的字节流,将其变为字符流,再用一个”BufferedReader”修饰,成为了一个自带缓冲区的字符流,这样的操作对处理纯文本更加合理.

            InputStream is = socket.getInputStream();            InputStreamReader isr = new InputStreamReader(is);            BufferedReader br = new BufferedReader(isr);            String msg = null;            while((msg = br.readLine())!=null){                jta.append("Client:"+msg+"\r\n");            }注意一点:        BufferedReader 的读取,是用.readline()方法,而不是read()方法,而且判断用null,而不是-1
1 0
原创粉丝点击