Swing聊天软件

前面做了Tcp和Udp的基本通信以及文件传输实验,是时候把这些内容整合在一起了。。
Swing就不介绍了,需要用到什么api都可以直接查。

一、基本聊天功能(服务端作中介,udp实现)

软件能够实现Windows主机和一台Linux虚拟机的通信。除此之外还需要一台Linux虚拟机作为服务端起到二者中介的作用。两个客户端与服务器的通信采用无连接的udp协议,服务器收到udp包直接向目标端口转发,不做其他任何操作。客户端在发送按钮事件里编写socket.send,同时new一个Thread并在此进程里编写socket.recieve,只有采用多线程才能保证聊天时能够同时收发信息。以上便可实现基本的聊天功能。
注意Win和Linux二者的编码有别。即

//Win客户端
byte[] buffer = text.getBytes("UTF-8");
...
//Linux客户端
byte[] buffer = text.getBytes("GBK");

二、文件传输功能(端到端,tcp实现)

文件传输采用tcp协议直接由端到端传输,这样的好处是传输效率高而且可靠、面向连接。除此之外,还需要多加一个收发信的确认功能。为了避免占用太多端口以及浪费过多线程,这里收发信还是使用原来的udp端口(而不是新建一个端口+线程)。那么就需要设计一个密文放在消息的开头以区分正常的聊天消息(我用的是三个井号"###"也可以更复杂点)。然后该密文还需要携带一些重要信息,包括:文件类型,文件名称,文件大小,主机ip以及端口号,后两者是为了告知目的主机使其与发送主机主动建立tcp连接(因为主机之间是不知道对方的ip和端口号的)。
文件传输的基本设计思路为:
发端:点击文件按钮→选择文件,获取文件、文件名等,发送密文,打开serversocket等待对方accept。
收端:收到udp消息,进行解析发现是密文,于是弹出对话框问是否接受。若选否则进行tcp连接,发送"no"消息,关闭socket。若选是则也进行tcp连接,发送"yes"消息,并准备接收文件。
发端:连接成功后,收到"no"则关闭连接,收到"yes"则准备发送文件。若是图片则使用字节流方法,文本文件则使用字符流方法。
其中传文本文件还要注意一下中文编码问题。在发端读取文件时,Win使用GBK编码,Linux使用UTF-8编码。在收端读取socket的inputStream时二者均使用UTF-8编码。

实验截图:

三、代码

1.Win客户端代码(ip:10.177.26.76,udp port:1080,tcp port:2080)

package gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;public class WinClient
{public static void main(String[] args) throws Exception{JFrame f = new JFrame();f.setTitle("16010410031 陈大至");f.setSize(720, 810);f.setLocation(100, 100);f.setLayout(null);JButton button = new JButton("发送");button.setBounds(610, 650, 80, 50);f.add(button);JButton imgButton = new JButton("图片");imgButton.setBounds(10,560,70,30);f.add(imgButton);JButton fileButton = new JButton("文本文件");fileButton.setBounds(100,560,90,30);f.add(fileButton);JTextArea textArea1 = new JTextArea();textArea1.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));textArea1.setLineWrap(true);textArea1.setBounds(10, 600, 590, 150);f.add(textArea1);JTextArea textArea2 = new JTextArea();textArea2.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));textArea2.setEditable(false);textArea2.setLineWrap(true);JScrollPane scrollPane = new JScrollPane(textArea2);f.add(scrollPane);textArea2.setBounds(10,10, 680, 540);f.add(textArea2);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);String hostname="192.168.131.135";//192.168.131.135String localhost="10.177.26.76";DatagramSocket socket1 = new DatagramSocket(1080);ServerSocket socket2 = new ServerSocket(2080);new Thread(() -> {while (true){try {byte[] buffer = new byte[1024];DatagramPacket packet = new DatagramPacket(buffer, buffer.length);socket1.receive(packet);String text = new String(packet.getData(),0,packet.getLength());String[] strings = text.split(";");if(strings[0].equals("###")){int option;String name=strings[2];String length=strings[3];String ip=strings[4];int port=Integer.parseInt(strings[5]);option = JOptionPane.showConfirmDialog(f,"收到文件:"+name+",大小:"+length+"kb,是否接收?");Socket socket = new Socket(ip,port);PrintWriter out = new PrintWriter(socket.getOutputStream(), true);if(strings[1].equals("img")){if(option==JOptionPane.OK_OPTION){out.println("yes");InputStream in = socket.getInputStream();FileOutputStream fileOut = new FileOutputStream("statics/保存图片.png");byte[] bytes = new byte[1024];int len;while((len = in.read(bytes))!=-1){fileOut.write(bytes, 0, len);}JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/保存图片.png");fileOut.close();in.close();}else{out.println("no");JOptionPane.showMessageDialog(f,"已取消接受文件。");}}else if(strings[1].equals("file")){if(option==JOptionPane.OK_OPTION){out.println("yes");BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),Charset.forName("UTF-8")));PrintWriter fileOut = new PrintWriter("statics/"+name);String s;while((s = in.readLine())!=null){System.out.println(s);fileOut.println(s);}fileOut.close();in.close();JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/"+name);}else{out.println("no");JOptionPane.showMessageDialog(f,"已取消接受文件。");}}out.close();socket.close();}else textArea2.append("对方:"+text+"\r\n");} catch (Exception e) {e.printStackTrace();}}}).start();button.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){String text = textArea1.getText();textArea2.append("你:"+text+"\r\n");try {byte[] buffer = text.getBytes("UTF-8");DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(hostname),1082);socket1.send(packet);textArea1.setText("");} catch (Exception ex) {ex.printStackTrace();}}});imgButton.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){try{JFileChooser fileChooser = new JFileChooser();fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);fileChooser.setCurrentDirectory(new File("D:\\"));fileChooser.setFileFilter(new FileNameExtensionFilter("Image Files","png","jpg","gif"));int result = fileChooser.showOpenDialog(f);if(result==JFileChooser.APPROVE_OPTION){File file = fileChooser.getSelectedFile();String filename = file.getName();Long length = file.length()/1024;String message = "###;img;"+filename+";"+length.toString()+";"+localhost+";2080";byte[] buffer = message.getBytes();DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);socket1.send(packet);Socket socket = socket2.accept();System.out.println("TCP连接成功");BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));if(reader.readLine().equals("yes")){FileInputStream fileIn = new FileInputStream(file);OutputStream out = socket.getOutputStream();byte[] bytes = new byte[1024];int len;while((len = fileIn.read(bytes))!= -1){out.write(bytes, 0, len);}JOptionPane.showMessageDialog(f,"文件传输成功。");fileIn.close();out.close();}else{JOptionPane.showMessageDialog(f,"文件被对方拒收。");}reader.close();socket.close();}}catch (Exception e1){e1.printStackTrace();}}});fileButton.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){try{JFileChooser fileChooser = new JFileChooser();fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);fileChooser.setCurrentDirectory(new File("D:\\"));fileChooser.setFileFilter(new FileNameExtensionFilter("Text Files","txt","doc","xls"));int result = fileChooser.showOpenDialog(f);if(result==JFileChooser.APPROVE_OPTION){File file = fileChooser.getSelectedFile();String filename = file.getName();Long length = file.length()/1024;String message = "###;file;"+filename+";"+length.toString()+";"+localhost+";2080";byte[] buffer = message.getBytes();DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);socket1.send(packet);Socket socket = socket2.accept();System.out.println("TCP连接成功");BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));if(reader.readLine().equals("yes")){BufferedReader fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("GBK")));PrintWriter out = new PrintWriter(socket.getOutputStream(),true);String s;while((s = fileIn.readLine())!=null){System.out.println(s);out.println(s);}JOptionPane.showMessageDialog(f,"文件传输成功。");fileIn.close();out.close();}else{JOptionPane.showMessageDialog(f,"文件被对方拒收。");}reader.close();socket.close();}}catch (Exception e1){e1.printStackTrace();}}});}
}

2.Linux客户端代码(ip:192.168.131.131,udp port:1081,tcp port:2081)

package gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;public class LinuxClient
{public static void main(String[] args) throws Exception{JFrame f = new JFrame();f.setTitle("16010410031 陈大至");f.setSize(700, 790);f.setLocation(900, 100);f.setLayout(null);JButton button = new JButton("发送");button.setBounds(610, 650, 80, 50);f.add(button);JButton imgButton = new JButton("图片");imgButton.setBounds(10,560,70,30);f.add(imgButton);JButton fileButton = new JButton("文本文件");fileButton.setBounds(100,560,90,30);f.add(fileButton);JTextArea textArea1 = new JTextArea();textArea1.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));textArea1.setLineWrap(true);textArea1.setBounds(10, 600, 590, 150);f.add(textArea1);JTextArea textArea2 = new JTextArea();textArea2.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));textArea2.setEditable(false);textArea2.setLineWrap(true);JScrollPane scrollPane = new JScrollPane(textArea2);f.add(scrollPane);textArea2.setBounds(10,10, 680, 540);f.add(textArea2);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);String hostname = "192.168.131.135";//192.168.131.135String localhost="192.168.131.131";//192.168.131.131DatagramSocket socket1 = new DatagramSocket(1081);ServerSocket socket2 = new ServerSocket(2081);new Thread(() -> {while (true){try {byte[] buffer = new byte[1024];DatagramPacket packet = new DatagramPacket(buffer, buffer.length);socket1.receive(packet);String text = new String(packet.getData(),0,packet.getLength());String[] strings = text.split(";");if(strings[0].equals("###")){int option;String name=strings[2];String length=strings[3];String ip=strings[4];int port=Integer.parseInt(strings[5]);option = JOptionPane.showConfirmDialog(f,"收到文件:"+name+",大小:"+length+"kb,是否接收?");Socket socket = new Socket(ip,port);PrintWriter out = new PrintWriter(socket.getOutputStream(), true);if(strings[1].equals("img")){if(option==JOptionPane.OK_OPTION){out.println("yes");InputStream inputStream = socket.getInputStream();FileOutputStream fileOut = new FileOutputStream("statics/保存图片.png");byte[] bytes = new byte[1024];int len;while((len = inputStream.read(bytes))!=-1){fileOut.write(bytes, 0, len);}JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/保存图片.png");fileOut.close();socket.close();}else{out.println("no");JOptionPane.showMessageDialog(f,"已取消接受文件。");socket.close();}}else if(strings[1].equals("file")){if(option==JOptionPane.OK_OPTION){out.println("yes");BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),Charset.forName("UTF-8")));PrintWriter fileOut = new PrintWriter("statics/"+name);String s;while((s = in.readLine())!=null){System.out.println(s);fileOut.println(s);}fileOut.close();in.close();JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/"+name);}else{out.println("no");JOptionPane.showMessageDialog(f,"已取消接受文件。");}}out.close();socket.close();}else textArea2.append("对方:"+text+"\r\n");} catch (Exception e) {e.printStackTrace();}}}).start();button.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){String text = textArea1.getText();textArea2.append("你:"+text+"\r\n");try {byte[] buffer = text.getBytes("GBK");DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(hostname),1082);socket1.send(packet);textArea1.setText("");} catch (Exception ex) {ex.printStackTrace();}}});imgButton.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){try{JFileChooser fileChooser = new JFileChooser();fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);fileChooser.setCurrentDirectory(new File("."));fileChooser.setFileFilter(new FileNameExtensionFilter("Image Files","png","jpg","gif"));int result = fileChooser.showOpenDialog(f);if(result==JFileChooser.APPROVE_OPTION){File file = fileChooser.getSelectedFile();String filename = file.getName();Long length = file.length()/1024;String message = "###;img;"+filename+";"+length.toString()+";"+localhost+";2081";byte[] buffer = message.getBytes();DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);socket1.send(packet);Socket socket = socket2.accept();System.out.println("TCP连接成功");BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));if(reader.readLine().equals("yes")){FileInputStream fileIn = new FileInputStream(file);OutputStream out = socket.getOutputStream();byte[] bytes = new byte[1024];int len;while((len = fileIn.read(bytes))!= -1){out.write(bytes, 0, len);}JOptionPane.showMessageDialog(f,"文件传输成功。");fileIn.close();out.close();}else{JOptionPane.showMessageDialog(f,"文件被对方拒收。");}reader.close();socket.close();}}catch (Exception e1){e1.printStackTrace();}}});fileButton.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){try{JFileChooser fileChooser = new JFileChooser();fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);fileChooser.setCurrentDirectory(new File("."));fileChooser.setFileFilter(new FileNameExtensionFilter("Text Files","txt","doc","xls"));int result = fileChooser.showOpenDialog(f);if(result==JFileChooser.APPROVE_OPTION){File file = fileChooser.getSelectedFile();String filename = file.getName();Long length = file.length()/1024;String message = "###;file;"+filename+";"+length.toString()+";"+localhost+";2081";byte[] buffer = message.getBytes();DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);socket1.send(packet);Socket socket = socket2.accept();System.out.println("TCP连接成功");BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));if(reader.readLine().equals("yes")){BufferedReader fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8")));PrintWriter out = new PrintWriter(socket.getOutputStream(),true);String s;while((s = fileIn.readLine())!=null){System.out.print(s);out.println(s);}JOptionPane.showMessageDialog(f,"文件传输成功。");fileIn.close();out.close();}else{JOptionPane.showMessageDialog(f,"文件被对方拒收。");}reader.close();socket.close();}}catch (Exception e1){e1.printStackTrace();}}});}
}

3.Linux服务器代码(ip:192.168.131.135,udp port:1082)

package gui;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;public class Server
{public static void main(String[] args) throws Exception{String hostname="",text;DatagramSocket socket = new DatagramSocket(1082);while(true){byte[] buffer = new byte[1024];DatagramPacket packet = new DatagramPacket(buffer, buffer.length);socket.receive(packet);text = new String(packet.getData(),0,packet.getLength());int port = packet.getPort();System.out.print("端口号:"+port+",");if(port==1080){System.out.println("来自Win主机:"+text);port=1081;hostname="192.168.131.131";//192.168.131.131}else if(port==1081){System.out.println("来自Ubuntu主机:"+text);port=1080;hostname="10.177.26.76";}else System.out.println("端口号错误");DatagramPacket packet2 = new DatagramPacket(packet.getData(), packet.getLength(), InetAddress.getByName(hostname),port);socket.send(packet2);}}
}

Java网络通信实验小记四:Swing聊天软件相关推荐

  1. 仿QQ聊天软件(登录界面、好友界面、聊天界面)-Java(Swing、Socket)

    文章目录 一.项目结构 二.项目功能 三.制作界面 (一).登录界面的制作 (二).好友列表界面 (三).聊天界面 四.制作服务器 五.设计通信协议 六.项目缺点 学习了socket通信后,就想来制作 ...

  2. java Swing局域网聊天软件+ 情侣电脑钢琴

    本文为姜友瑶原创作品 非商业转载请注明作译者.出处,并保留本文的原始链接.否则追究法律责任!商业转载请联系作者! 更多作品请访问我的个人网站 www.jyymatrix.cc 2013年的时候刚刚看完 ...

  3. 合肥工业大学宣城校区Java技术实验二 基于GUI的网络通信程序设计

    一.实验目的 1.掌握Java中GUI程序的编写,包括事件监听机制. 2.掌握Java的网络通信编程,ServerSocket,Socket类的使用. 3.掌握Java中多线程的编程,Thread类, ...

  4. java程序设计——实验四

    <Java程序设计>实 验 报 告(四) 实验名称:java编程基础 实验地点:10-306 所使用的工具软件及环境: JDK1.7或1.8与Eclipse 一.实验目的: 了解图形用户界 ...

  5. Java实验:编写网络聊天程序(图形界面)

    课程名称 高级Java程序设计 实验项目 Java网络编程 实验目的: 使用客户机/服务器模式.基于TCP协议编写一对多"群聊"程序.其中客户机端单击"连接服务器&quo ...

  6. Java+Swing聊天室

    Java+Swing聊天室 一.系统介绍 二.系统展示 1.发送消息 2.清屏 三.系统实现 四.其他 1.其它系统 2.获取源码 一.系统介绍 本系统实现了简单的聊天室功能:发送消息.清屏.退出系统 ...

  7. Java实现聊天软件(一)界面编写

    文章目录 Java实现聊天软件(一)界面编写 介绍 IM(Instant Messenger)工作原理 登录界面 界面设计 代码实现 导包 继承建类 定义组件 构造函数 成品展示 好友栏界面 例子展示 ...

  8. Java实现 简单聊天软件

    简单的聊天软件 //客户端package yjd9; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; ...

  9. 20145240 《Java程序设计》第四次实验报告

    20145240 <Java程序设计>第四次实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1452 指导教师:娄嘉鹏 实验日期:2016.04.26 实验 ...

最新文章

  1. CentOS7下Docker Storage Pool扩容
  2. 和lock一起学beego 博客系统开发为例(五)
  3. Excel 2010单元格中设置表头
  4. ubuntu 启动器
  5. linux的grup文件,Linux /boot/grub/grub.conf(GRUB配置文件)内容详解
  6. python排序函数set_【Python】排列组合itertools 集合set
  7. 我会手动创建线程,为什么让我使用线程池?
  8. RTMPdump(libRTMP)源代码分析 4: 连接第一步——握手(Hand Shake)
  9. css3轮播不用jpuery_js和CSS3 3D轮播图
  10. MFC体系结构(3)
  11. 软件巨头Salesforce带来AutoML杀手TransmogrifAI
  12. spring cloud 学习(5) - config server
  13. SpringApplication#run⽅法的第6步,创建ApplicationContext(五)
  14. bootdo跳sign in页面
  15. android 获取经纬度的三种方法,Android简单获取经纬度的方法
  16. 互联网晚报 | 10月29日 星期五 | 理想汽车第10万辆整车正式下线;微博新增“炸毁评论”功能;《长津湖》续集正式官宣...
  17. 《美团机器学习实践》学习笔记:机器学习中的模型评价指标(二)——回归模型评估
  18. linux越狱时手机怎么进入dfu,iOS详细越狱步骤 进入DFU模式_iPhone资讯_太平洋电脑网PConline...
  19. 卧槽!我的世界也有开源版本了!!!
  20. 学习-软件测试-Selenium-unittest-Maven-Jmeter

热门文章

  1. EMC Select计划首现国内厂商 迪思杰拔头筹
  2. 无法加载文件 ******.ps1,因为在此系统中禁止执行脚本。有关详细信息,请参阅 get-help about_signing
  3. SLIC 超像素分割详解(三):应用
  4. 宏定义函数和普通函数
  5. 总在说双亲委派,但双亲委派是什么,双亲委派和类加载的关系,简单讲解
  6. jquery的ajax常用写法
  7. kindeditor html上传本地图片
  8. 数据预处理--缺失值填补《菜菜学习笔记》
  9. sql语句语法数据定义语句alter table
  10. maven使用命令行打包