赞
踩
说明:如果一个 类,需要有界面的显示,那么该类就需要继承自JFrame,此时,该类就可以被称为一个“窗体类"。
服务端代码:
- package cn.qy.chat;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.KeyEvent;
- import java.awt.event.KeyListener;
- import java.io.*;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.Properties;
-
- //说明:如果一个类,需要有界面的显示,那么该类就需要继承自JFrame,此时,该类就可以被称为一个“窗体类"
- //1.定义JFrame窗体中的组件
- //2.在构造方法中初始化组件
- //3.使用网络编程完成数据的传输(TCP,UDP协议)
- //4.实现“发送”按钮的监听点击事件。需要注意的是,文本域拼接数据时,需要自己换行,不要在发送数据时换行。
- public class ServerChatMain extends JFrame implements ActionListener, KeyListener {
-
- public static void main(String[] args) {
- // 调用构造器
- new ServerChatMain();
- }
- //属性
-
- //文本域
- private JTextArea jta;
- //滚动条
- private JScrollPane jsp;
- //面板
- private JPanel jp;
- //文本框
- private JTextField jtf;
- //按钮
- private JButton jb;
-
- //流
- BufferedReader br;
- BufferedWriter bw;
-
- //服务端端口号
- private static int serverPort;
- //静态代码块加载外部配置文件
- //特点1:在类加载时,自动执行
- //特点2:一个类只会加载一次,因此静态代码块只会执行一次
- static {
- Properties prop = new Properties();
- try {
- prop.load(new FileReader("chat.properties"));
- serverPort =Integer.parseInt(prop.getProperty("serverPort"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- //创建空参构造器
- public ServerChatMain(){
- //初始化组件
-
- //初始化文本域
- jta = new JTextArea();
- //设置文本域不可编辑
- jta.setEditable(false);
- //将文本域添加到滚动条中,实现滚动效果
- jsp = new JScrollPane(jta);
-
- //面板
- jp = new JPanel();
- jtf = new JTextField(15);
- jb = new JButton("发送");
- //将文本框与按钮添加到面板中
- jp.add(jtf);
- jp.add(jb);
-
- //将滚动条与面板全部添加到窗体中
- this.add(jsp, BorderLayout.CENTER);
- this.add(jp, BorderLayout.SOUTH);
-
- //设置 标题,大小,位置,关闭,是否可见
- this.setTitle("QQ 服务端");
- this.setSize(300,300);
- this.setLocation(600,300);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体关闭,程序退出
- this.setVisible(true);
-
- /******************TCP 服务端 start*****************/
-
- //给发送按钮绑定一个监听点击事件
- jb.addActionListener(this);
- //给文本框绑定一个键盘点击事件
- jtf.addKeyListener(this);
- //接收客户端数据,并回显到自己的文本域
- try {
- //1.创建一个服务端的套接字socket
- ServerSocket serverSocket = new ServerSocket(serverPort);
- //2.等待客户端的链接
- Socket socket = serverSocket.accept();//客户端对象
- //3.获取socket 通道的输入流(输入流是实现读取数据的,一行一行读取,因此用BufferedReader-->readLine
- br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-
- //4.获取socket 通道的输出流(输出流实现写出数据,也是写一行,换一行,刷新)BufferedWriter-->new Line()
- //什么时候需要写出数据?当用户点击发送按钮时
- bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
-
- //循环读取数据,并把它拼接到文本域中
- String line = null;
- while ((line=br.readLine())!=null){
- //将读取的数据拼接到文本域中显示
- jta.append(line+System.lineSeparator());
- }
- //5.关闭serverSocket 通道
- serverSocket.close();
-
- } catch (IOException e) {
- e.printStackTrace();
- }
-
-
-
- /******************TCP 服务端 end*****************/
-
- }
-
- //行为
- /**
- * 重新ActionListener中的1个方法,实现点击 发送键 发送
- * @param e
- */
- @Override
- public void actionPerformed(ActionEvent e) {
- sendDataToSocket();
- }
- /**
- * 重写KeyListener中的3个方法,实现Enter键发送
- * @param e
- */
- @Override
- public void keyPressed(KeyEvent e) {
- //回车键
- if (e.getKeyCode()== KeyEvent.VK_ENTER){
- //发送数据到socket通道
- sendDataToSocket();
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
-
- }
-
- //方法功能:发送数据到客户端,并将内容回显到自己的文本域
- public void sendDataToSocket(){
- //1.获取文本框中的内容
- String text = jtf.getText();
- //2.拼接需要发送的数据内容
- text = "服务端对客户端说:"+text;
- //3.自己也需要显示
- jta.append(text+System.lineSeparator());
-
- try {
- //4.发送
- bw.write(text);
- bw.newLine();
- bw.flush();
- //5.清空文本框
- jtf.setText("");
- } catch (Exception exception) {
- exception.printStackTrace();
- }
- }
- }
客户端代码:
- package cn.qy.chat;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.KeyEvent;
- import java.awt.event.KeyListener;
- import java.io.*;
- import java.net.Socket;
- import java.util.Properties;
-
- //说明:如果一个类,需要有界面的显示,那么该类就需要继承自JFrame,此时,该类就可以被称为一个“窗体类
- //1.定义JFrame窗体中的组件
- //2.在构造方法中初始化组件
- public class ClientChatMain extends JFrame implements ActionListener, KeyListener {
-
- public static void main(String[] args) {
- // 调用构造器
- new ClientChatMain();
- }
- //属性
-
- //文本域
- private JTextArea jta;
- //滚动条
- private JScrollPane jsp;
- //面板
- private JPanel jp;
- //文本框
- private JTextField jtf;
- //按钮
- private JButton jb;
-
- //流
- BufferedReader br;
- BufferedWriter bw;
-
- //通信的IP和Port
- private static int clientPort;
- private static String clientIP;
- //静态代码块加载外部配置文件
- //特点1:在类加载时,自动执行
- //特点2:一个类只会加载一次,因此静态代码块只会执行一次
- static {
- Properties prop = new Properties();
- try {
- prop.load(new FileReader("chat.properties"));
- clientPort = Integer.parseInt(prop.getProperty("clientPort"));
- clientIP = prop.getProperty("clientIP");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- //创建构造器
- public ClientChatMain(){
- //初始化组件
-
- //初始化文本域
- jta = new JTextArea();
- //设置文本域不可编辑
- jta.setEditable(false);
-
- //将文本域添加到滚动条中,实现滚动效果
- jsp = new JScrollPane(jta);
- //面板
- jp = new JPanel();
- jtf = new JTextField(15);
- jb = new JButton("发送");
- //将文本框与按钮添加到面板中
- jp.add(jtf);
- jp.add(jb);
-
- //将滚动条与面板全部添加到窗体中
- this.add(jsp, BorderLayout.CENTER);
- this.add(jp, BorderLayout.SOUTH);
-
- //设置 标题 大小,位置,关闭,是否可见
- this.setTitle("QQ 客户端");
- this.setSize(300,300);
- this.setLocation(300,300);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体关闭,程序退出
- this.setVisible(true);
-
- /******************TCP 客户端 start*****************/
- //给发送按钮绑定一个监听点击事件
- jb.addActionListener(this);
- //给键盘绑定单击事件
- jtf.addKeyListener(this);
- //接受服务端数据,并回显到自己的文本域
- try {
- //1.创建一个客户端的套接字socket
- Socket socket = new Socket(clientIP, clientPort);
- //2.获取socket 通道的输入流
- br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
- //3.获取socket 通道的输出流
- bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
-
- //循环读取数据,并把它拼接到文本域中
- String line =null;
- while ((line=br.readLine())!=null){
- jta.append(line+System.lineSeparator());
- }
-
- //4.关闭socket 通道
- socket.close();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- /******************TCP 客户端 end*****************/
-
- }
-
- //行为
-
- /**
- * 重新ActionListener中的1个方法,实现点击 发送键 发送
- * @param e
- */
- @Override
- public void actionPerformed(ActionEvent e) {
- sendDataToSocket();
- }
-
- /**
- * 重写KeyListener中的3个方法,实现Enter键发送
- * @param e
- */
- @Override
- public void keyPressed(KeyEvent e) {
- if (e.getKeyCode()==KeyEvent.VK_ENTER){
- sendDataToSocket();
- }
- }
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
-
- }
-
- //方法功能:发送数据到服务端,并将内容回显到自己的文本域
- private void sendDataToSocket(){
- //1.获取文本框中的内容
- String text = jtf.getText();
- //2.拼接需要发送的数据内容
- text = "客户端对服务端说:"+text;
- //3.自己也需要显示
- jta.append(text+System.lineSeparator());
-
- try {
- //4.发送
- bw.write(text);
- bw.newLine();
- bw.flush();
- //5.清空文本框
- jtf.setText("");
- } catch (Exception exception) {
- exception.printStackTrace();
- }
- }
- }
启动时,必须先启动服务端,再启动客户端。
最终效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。