Java基于TCP方式的二进制文件传输

一个基于Java Socket协议之上文件传输的完整示例,基于TCP通信完成。

除了基于TCP的二进制文件传输,还演示了JAVA Swing的一些编程技巧,Demo程序

实现主要功能有以下几点:

  • 1.基于Java Socket的二进制文件传输(包括图片,二进制文件,各种文档work,PDF)
  • 2.SwingWorker集合JProgressBar显示实时传输/接受完成的百分比
  • 3.其它一些Swing多线程编程技巧

首先来看一下整个Dome的Class之间的关系图:

下面按照上图来详细解释各个类的功能与代码实现:

服务器端:

FileTransferServer类的功能首先是在端口9999创建一个服务器套接字并

开始监听连接。相关代码如下:

private void startServer(int port) {
 try {
  serverSocket = new ServerSocket(port);
  System.out.println("Server started at port :" + port);
  while(true) {
   Socket client = serverSocket.accept(); // blocked & waiting for income socket
   System.out.println("Just connected to " + client.getRemoteSocketAddress());
   FileReceiveTask task = new FileReceiveTask(client);
   bar.setValue(0); // reset it now
   task.addPropertyChangeListener(new PropertyChangeListener() {
    public void propertyChange(PropertyChangeEvent evt) {
     if ("progress".equals(evt.getPropertyName())) {
      bar.setValue((Integer) evt.getNewValue());
     }
    }
   }); 

   task.execute();
  } 

 } catch (IOException e) {
  e.printStackTrace();
 }
}

关于PropertyChangeListener, Java提供了一个非常有力的工具类来
监控任意Bean Model的数据改变,程序通过添加该监听器实现对

SwingWorker的progress属性值改变的事件捕获,然后更新JProgressBar

实例对象,实现了UI的刷新。FileTransferServer类的完整源代码如下:

package com.gloomyfish.socket.tutorial.filetransfer; 

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; 

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar; 

public class FileTransferServer extends JFrame implements ActionListener {
 /**
  *
  */
 public final static String START_SVR = "Start";
 public final static String SHUT_DOWN_SVR = "Shut Down";
 public final static String END_FLAG = "EOF";
 private static final long serialVersionUID = 1L;
 private ServerSocket serverSocket;
 private JButton startBtn;
 private JProgressBar bar;
 public FileTransferServer() {
  super("File Server");
  initComponent();
  setupListener();
 } 

 private void setupListener() {
  startBtn.addActionListener(this);
 } 

 private void initComponent() {
  startBtn = new JButton(START_SVR);
  JPanel progressPanel = new JPanel();
  progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS));
  bar = new JProgressBar();
  bar.setMinimum(0);
  bar.setMaximum(100);
  progressPanel.add(bar);
  getContentPane().setLayout(new BorderLayout());
  JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  btnPanel.add(startBtn);
  getContentPane().add(btnPanel, BorderLayout.SOUTH);
  getContentPane().add(progressPanel, BorderLayout.CENTER);
 } 

 private void startServer(int port) {
  try {
   serverSocket = new ServerSocket(port);
   System.out.println("Server started at port :" + port);
   while(true) {
    Socket client = serverSocket.accept(); // blocked & waiting for income socket
    System.out.println("Just connected to " + client.getRemoteSocketAddress());
    FileReceiveTask task = new FileReceiveTask(client);
    bar.setValue(0); // reset it now
    task.addPropertyChangeListener(new PropertyChangeListener() {
     public void propertyChange(PropertyChangeEvent evt) {
      if ("progress".equals(evt.getPropertyName())) {
       bar.setValue((Integer) evt.getNewValue());
      }
     }
    }); 

    task.execute();
   } 

  } catch (IOException e) {
   e.printStackTrace();
  }
 } 

 public void showSuccess() {
  bar.setValue(100);
  JOptionPane.showMessageDialog(this, "file received successfully!");
 } 

 @Override
 public void actionPerformed(ActionEvent e) {
  if(START_SVR.equals(e.getActionCommand())) {
   Thread startThread = new Thread(new Runnable() {
    public void run() {
     startServer(9999);
    }
   });
   startThread.start();
   startBtn.setEnabled(false);
  } else if(SHUT_DOWN_SVR.equals(e.getActionCommand())) { 

  } else {
   // do nothing...
  }
 } 

 public static void main(String[] args) {
  FileTransferServer server = new FileTransferServer();
  server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  server.setSize(400, 400);
  server.setResizable(false);
  server.setVisible(true);
 }
}

FileReceiveTask是服务器端的文件接受类:
首先从建立的TCP流中得到文件名与文件大小,然后开始接受文件内容字节

并写入创建的文件对象流中,最后验证文件大小与写入的字节流是否相等

最后发送一条消息到文件发送方,告诉对方文件传输完成,可以关闭TCP流。

该类的完整源代码如下:

package com.gloomyfish.socket.tutorial.filetransfer; 

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket; 

import javax.swing.SwingWorker; 

public class FileReceiveTask extends SwingWorker<Integer, Object> {
 private Socket _mSocket;
 public FileReceiveTask(Socket client) {
  this._mSocket = client;
 } 

 @Override
 protected Integer doInBackground() throws Exception {
  // get file meta information
  DataInputStream input = new DataInputStream(_mSocket.getInputStream());
  String fileName = input.readUTF();
  int fileLength = (int)input.readLong(); // number of total bytes
  File file = new File("C:\\Users\\fish\\Downloads" + File.separator + fileName);
  BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
  System.out.println("Received File Name = " + fileName);
  System.out.println("Received File size = " + fileLength/1024 + "KB"); 

  // start to receive the content of the file and write them
  byte[] content = new byte[2048];
  int offset = 0;
  int numReadBytes = 0;
  while(offset < fileLength && (numReadBytes = input.read(content)) > 0) {
   output.write(content, 0, numReadBytes);
   float precent = 100.0f * ((float)offset)/((float)fileLength);
   setProgress((int)precent);
   offset += numReadBytes;
  }
  System.out.println("numReadBytes = " + numReadBytes);
  if(offset < fileLength) {
   numReadBytes = input.read(content);
   System.out.println("numReadBytes = " + numReadBytes);
   System.out.println("File content error at server side");
  } else {
   System.out.println("File Receive Task has done correctly");
  }
  setProgress(100); 

  // tell client to close the socket now, we already receive the file successfully!!
  BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(_mSocket.getOutputStream()));
  bufferedWriter.write("DONE\r\n");
  bufferedWriter.flush(); 

  // close the file and socket
  output.close();
  _mSocket.close();
  return 100;
 } 

}

客户端:
FileTransferClient是客户端UI类,用来实现到服务端的连接,然后选择

要传输的文件(图片,PDF,Word文档等各种二进制文件)。如果没有

输入服务器信息,会弹出提示要求输入。端口已经指定为:9999

【send File】按钮会打开文件选择框,用户选择要传输文件以后,创建

FileTransferTask线程,并开始执行文件传送。客户端UI代码如下:

package com.gloomyfish.socket.tutorial.filetransfer; 

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.InetSocketAddress;
import java.net.SocketAddress; 

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
/**
 * 我一般写英文注释,偶尔我也会写中文注释,只是觉得写英文
 * 注释跟代码比较统一,无他。
 */
public class FileTransferClient extends JFrame implements ActionListener {
 /**
  *
  */
 private static final long serialVersionUID = 1L;
 public final static String SEND_CMD = "Send File";
 public final static int MINIMUM = 0;
 public final static int MAXIMUM = 100;
 // public final static String CONNECT_CMD = "Connect";
 private JButton sendFileBtn;
 private JTextField serverField;
 private JTextField portField;
 private JProgressBar bar; 

 public FileTransferClient() {
  super("File Transfer Client");
  initComponents();
 } 

 private void initComponents() {
  getContentPane().setLayout(new BorderLayout());
  JPanel progressPanel = new JPanel();
  progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS));
  bar = new JProgressBar();
  progressPanel.add(bar);
  bar.setMinimum(MINIMUM);
  bar.setMaximum(MAXIMUM);
  JPanel serverSettingPanel = new JPanel();
  serverSettingPanel.setLayout(new GridLayout(2,2,5,5));
  serverSettingPanel.setBorder(BorderFactory.createTitledBorder("Server Setting"));
  serverField = new JTextField();
  portField = new JTextField();
  serverSettingPanel.add(new JLabel("Server IP/Host:"));
  serverSettingPanel.add(serverField);
  serverSettingPanel.add(new JLabel("Server Port:"));
  serverSettingPanel.add(portField); 

  sendFileBtn = new JButton(SEND_CMD);
  JPanel btnPanel = new JPanel();
  btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
  btnPanel.add(sendFileBtn);
  getContentPane().add(serverSettingPanel, BorderLayout.NORTH);
  getContentPane().add(btnPanel, BorderLayout.SOUTH);
  getContentPane().add(progressPanel, BorderLayout.CENTER);
  sendFileBtn.addActionListener(this);
 } 

 @Override
 public void actionPerformed(ActionEvent e) {
  String command = e.getActionCommand();
  if(command.equals(SEND_CMD)) {
   if(checkNull()) {
    JOptionPane.showMessageDialog(this, "Please enter server host and port in order to set up the connection!");
    return;
   }
   JFileChooser chooser = new JFileChooser();
   int status = chooser.showOpenDialog(null);
   if (status == JFileChooser.APPROVE_OPTION) {
    File f = chooser.getSelectedFile();
    SocketAddress address = new InetSocketAddress(getServer(), getPort());
    FileTransferTask task = new FileTransferTask(f, address, this);
    bar.setValue(0);
    task.addPropertyChangeListener(new PropertyChangeListener() {
     public void propertyChange(PropertyChangeEvent evt) {
      if ("progress".equals(evt.getPropertyName())) {
       bar.setValue((Integer) evt.getNewValue());
      }
     }
    });
    task.execute(); // 异步task执行
   }
  } else {
   // do nothing
  }
 } 

 public void showSuccess() {
  bar.setValue(100);
  JOptionPane.showMessageDialog(this, "file send successfully!");
 } 

 public String getServer() {
  return serverField.getText().trim();
 } 

 public int getPort() {
  return Integer.parseInt(portField.getText().trim());
 }
 /**
  * make sure the UI already have some correct input information here!!!
  * @return
  */
 private boolean checkNull() {
  String serverName = serverField.getText();
  String port = portField.getText();
  if(serverName == null || serverName.length() == 0 || port == null || port.length() == 0) {
   return true;
  } 

  try {
   Integer.parseInt(port); // try to parse it as server port number , validation code.
  } catch(NumberFormatException ne) {
   ne.printStackTrace();
   return true;
  }
  return false;
 } 

 public static void main(String[] args) {
  FileTransferClient client = new FileTransferClient();
  client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  client.setSize(400, 400);
  client.setResizable(false);
  // client.pack();
  client.setVisible(true);
 } 

}

FileTransferTask实现的功能主要有:

  • 1. 发送文件meta信息到接受方(文件名与文件大小)
  • 2. 读取文件内容字节写入Socket字节流中,发送到接受方
  • 3. 从Socket字节流中读取对方接受完成通知信息,调用弹出文件传输成功信息

该类完全源代码如下:

package com.gloomyfish.socket.tutorial.filetransfer; 

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketAddress; 

import javax.swing.SwingWorker; 

public class FileTransferTask extends SwingWorker<Integer, Object> {
 private File selectedFile;
 private Socket mSocket;
 private SocketAddress address;
 private FileTransferClient parent; 

 public FileTransferTask(File file, SocketAddress address, FileTransferClient owner /*, JProgressBar progress*/) {
  this.address = address;
  this.selectedFile = file;
  mSocket = new Socket();
  this.parent = owner;
 } 

 @Override
 protected Integer doInBackground() throws Exception {
  // Get the size of the file
  long length = selectedFile.length();
  if (length > Integer.MAX_VALUE) {
   throw new IOException("Could not completely read file " + selectedFile.getName() + " as it is too long (" + length + " bytes, max supported " + Integer.MAX_VALUE + ")");
  } 

  mSocket.connect(address); 

  // Create the byte array to hold the file data
  mSocket.setSoLinger(true, 60);
  DataOutputStream dout = new DataOutputStream(mSocket.getOutputStream());
  // now we start to send the file meta info.
  dout.writeUTF(selectedFile.getName());
  dout.writeLong(length);
  dout.flush();
  // end comment
  FileDataPackage pData = new FileDataPackage();
  DataInputStream is = new DataInputStream(new FileInputStream(selectedFile));
  byte[] bytes = new byte[2048]; 

  // Read in the bytes
  int offset = 0;
  int numRead = 0;
  int fsize = (int)length;
  while (offset < fsize && (numRead=is.read(bytes, 0, bytes.length)) >= 0) {
   pData.setData(bytes, numRead);
   dout.write(pData.getPackageData(), 0, pData.getPackageData().length);
   dout.flush();
   offset += numRead;
   float precent = 100.0f * ((float)offset)/((float)fsize);
   setProgress((int)precent);
  }
  System.out.println("total send bytes = " + offset);
  // Ensure all the bytes have been read in
  if (offset < fsize) {
   throw new IOException("Could not completely transfer file " + selectedFile.getName());
  }
  mSocket.shutdownOutput(); 

  // receive the file transfer successfully message from connection 

  BufferedInputStream streamReader = new BufferedInputStream(mSocket.getInputStream());
  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(streamReader));
  String doneMsg = bufferedReader.readLine();
  if("DONE".equals(doneMsg)) {
   parent.showSuccess();
  }
  // Close the file input stream
  setProgress(100);
  // dout.close();
  mSocket.close();
  is.close();
  System.out.println("close it now......");
  return 100;
 }
}

数据包类如下,不解释!

package com.gloomyfish.socket.tutorial.filetransfer;
/**
 * this is very simple file transfer protocol over TCP socket
 */
public class FileDataPackage { 

 private int dataLength; // 数据包中数据长度,两个字节
 private byte[] databuff; // 数据包中数据,meici最大不超过2048字节 

 public final static byte[] EOF = new byte[]{'E', 'O','F'}; 

 public FileDataPackage() {
  dataLength = 0;
  databuff = new byte[2048];
 } 

 public byte[] getPackageData() {
  byte[] pData = new byte[dataLength];
  // end comment
  System.arraycopy(databuff, 0, pData, 0, dataLength);
  return pData;
 } 

 public void setData(byte[] data, int bsize) {
  dataLength = bsize;
  for(int i=0; i<databuff.length; i++) {
   if(i<bsize) {
    databuff[i] = data[i];
   } else {
    databuff[i] = ' ';
   }
  }
 }
}

每次发送的最大字节数为2048个字节。程序最终运行效果如下(win7 + JDK6u30):

以上就是本文的全部内容,希望对大家的学习有所帮助。

(0)

相关推荐

  • java读写二进制文件的解决方法

    接口:Writerable 复制代码 代码如下: package com.geoway.pad.common; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; public interface Writerable {        //write         public void  write(DataOutput data) throws IOException;     

  • Java实现较大二进制文件的读、写方法

    由于项目需要,需要对二进制文件进行读写.转换. 文件说明:由其他程序得到的二进制文件,文件内容为:包含23543个三角形.13270个顶点的三角网所对应的721组流速矢量(u.v)文件,通俗些说,一条数据包含两个双精度型的数值,每组数组包含23543条数据,如果以一个双精度数值为单位,则总共有23543 * 721 * 2 =33,949,006条数据.由Fortran程序以每 8 Byte存储一个数值的二进制文件存储,最终文件大小为下图所示: 测试:从该文件读出数据之后,转换为十进制,存储到另

  • JAVA中读取文件(二进制,字符)内容的几种方法总结

    JAVA中读取文件内容的方法有很多,比如按字节读取文件内容,按字符读取文件内容,按行读取文件内容,随机读取文件内容等方法,本文就以上方法的具体实现给出代码,需要的可以直接复制使用 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如图片.声音.影像等文件. */ public static void readFileByBytes(String fileName) { File file = new File(fileName); In

  • java判断一个文件是否为二进制文件的方法

    本文实例讲述了java判断一个文件是否为二进制文件的方法.分享给大家供大家参考.具体如下: public static boolean isBinary(File file) { boolean isBinary = false; try { FileInputStream fin = new FileInputStream(file); long len = file.length(); for (int j = 0; j < (int) len; j++) { int t = fin.rea

  • java实现解析二进制文件的方法(字符串、图片)

    1.需求说明,实现细节要求: 解析二进制文件 files\case10\binary,其中包含一个字符串和一张图片,数据文件格式为字符串数据长度(2字节)+字符串内容+图片数据长度(4字节)+图片数据,数据长度均为数据字节长度,高位在后,字符串为UTF-8编码,请解析,输出字符串内容,图片文件保存为files\case10\test.png. 2.实现代码: package com.igen.case10; import java.io.File; import java.io.FileInpu

  • 利用Java读取二进制文件实例详解

    前言 本文主要给大家介绍了关于Java读取二进制文件的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 读Hex写CSV data目录下有little-endian bin文件,2个字节代表一个数字. bin存储的数据格式可自己定义.相同的方法可以直接应用到Android中. `-- networkProj |-- data |-- networkProj.iml |-- out `-- src 实现方法 private static void convertFiles

  • java实现插入mysql二进制文件,blob类型,遇到问题及解决办法

    首先是数据库建立要准备的: 我们要把放置二进制字段设置为Blob类型,根据文件的大小选择合适的Blob类型,一下是各个Blob类型所能容纳二进制文件的大小 MySQL的四种BLOB类型 类型 大小(单位:字节) TinyBlob 最大 255 Blob 最大 65K MediumBlob 最大 16M LongBlob 最大 4G 一下是具体操作代码: 复制代码 代码如下: /** * * 把二进制文件(该二进制文件可以是本地硬盘路径,也可以是一个网络路径)存入数据库 * create date

  • Java基于TCP方式的二进制文件传输

    一个基于Java Socket协议之上文件传输的完整示例,基于TCP通信完成. 除了基于TCP的二进制文件传输,还演示了JAVA Swing的一些编程技巧,Demo程序 实现主要功能有以下几点: 1.基于Java Socket的二进制文件传输(包括图片,二进制文件,各种文档work,PDF) 2.SwingWorker集合JProgressBar显示实时传输/接受完成的百分比 3.其它一些Swing多线程编程技巧 首先来看一下整个Dome的Class之间的关系图: 下面按照上图来详细解释各个类的

  • Java基于TCP协议的Socket通信

    目录 简介 TCP简介 JAVA Socket简介 SocketImpl介绍 TCP 编程 构造ServerSocket 1.1 绑定端口 1.2 设定客户连接请求队列的长度 1.3 设定绑定的IP 地址 1.4 默认构造方法的作用 多线程示例 简介 TCP简介 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户

  • Java 基于tcp协议实现文件上传

    服务端 package lesson02; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * 服务端接收文件 */ public class TcpServerDemo2 { public static void main(String[] args) throws IOException { //1.创建服务 ServerSocket serverSocket = new ServerSo

  • Java基于Tcp协议的socket编程实例

    本文实例讲述了Java基于Tcp协议的socket编程方法,分享给大家供大家参考.具体分析如下: 以下是一对一的通信编程实现,后续会继续学习一个服务器监听多个客户端的实现. 这里用到的主要步骤如下: 第一步:以特定端口(如4800)新建socket对象 第二步:以系统输入设备构造BufferedReader对象,该对象用于接收系统键盘输入的字符 第三步:以socket对象 得到输出流来构造PrintWriter 第四步:以socket对象得到输入流来构造相应的BufferedReader对象,该

  • Java基于栈方式解决汉诺塔问题实例【递归与非递归算法】

    本文实例讲述了Java基于栈方式解决汉诺塔问题.分享给大家供大家参考,具体如下: /** * 栈方式非递归汉诺塔 * @author zy * */ public class StackHanoi { /** * @param args */ public static void main(String[] args) { System.out.println("我们测试结果:"); System.out.println("递归方式:"); hanoiNormal(

  • Java基于Tcp的基础聊天功能实例

    本文实例讲述了Java基于Tcp的基础聊天功能.分享给大家供大家参考,具体如下: 最基础的聊天,用户端和服务器端每次说一句,而且严格规定了先后到顺序. 服务器端: import java.io.*; import java.net.*; public class ChatServer { public static void main(String[] args) { ServerSocket server = null; try { server = new ServerSocket(1213

  • Java基于TCP协议socket网络编程的文件传送的实现

    先了解一下socket基本概念 socket也叫套接字: 是指在网路中不同主机上的应用进程之间,进行双向通信的端点的抽象. 简单理解就是: 两个主机之间要通信,就需要知道彼此的ip,端口号等信息,而一台主机这些信息的集合: 就可以理解为一个端点,即为套接字 双方通过套接字作为一种坐标,建立信息通道,形成连接(两点连接一条直线) 简单理解了套接字的概念后,来看看如何通过java socket编程来实现 两台主机文件的接收与发送: 代码如下: 发送方: import java.io.*; impor

  • Java 基于TCP Socket 实现文件上传

    文件上传过程一个单向Socket通信过程.客户端通过文件输入流读取文件,然后从Socket获取输出流写入数据.服务端从Socket中获得输入流,然后写入文件输出流,写入数据完成则上传完成. 服务端UploadServer: public class UplaodServer { public static void main(String []args){ try( // 创建一个ServerSocket监听8080端口的请求 // ServerSocket 实现了 AutoCloseable接

  • java基于TCP协议实现聊天程序

    JAVA程序设计之基于TCP协议的socket聊天程序 ,供大家参考,具体内容如下 一.程序实现的功能 1.进入客户端界面 2.创建昵称 3.群发信息 4.@私聊 5.下线通知 6.在线人数统计 二.整体架构图 三.简单介绍 本程序实现了基于TCP通信的聊天程序: 1 服务器端: 服务器端继承JFrame框架,添加组件.创建服务器端的socket,起一个线程池,每接收到一个客户端的连接,分配给其一个线程处理与客户端的通信,将每个客户端的昵称和服务器分配给其的输出流存储到哈希表中.通过检索哈希表中

  • Java基于Tcp/ip连接的多人交互聊天室

    本文实例为大家分享了Java  Socket编程实现多人交互聊天室的具体代码,供大家参考,具体内容如下 本项目由三个.java文件(Client.java.Server.java.UI.java)和一个.jpg图片文件组成UI.java是负责界面的构成文件.本聊天室的界面极其简单.主要分为两个界面:第一个是启动时需要登陆的界面如下: 输入名字进去以后就可以直接聊天     这个聊天室相当于群聊,每一个登陆进去的人发的信息,其他人都会收到. 使用指南: 1.运行Server.java文件,保证服务

随机推荐