String byte[] 的互相转换
使用String.getBytes(String charset)方法將string 轉換為 byte[]
· 其中charset 有UTF-8 UNICODE GBK ISO8859-1。
使用new String(byte[] bytes, String charset)方法將byte[]轉換為string
byte name[] =sendFile.getName().getBytes("utf-8");
byte name_temp3[] = new byte[nameLen]; for (int i = 0; i < nameLen; i++) { name_temp3[i] = all[length - nameLen - 4 + i]; } String ch_name=new String(name_temp3,"UTF-8");对于Socket 和ServerSokcet也有一定的了解。結構大概是這樣的:
private class runFileServer extends MyThread { public void run() { ServerSocket server = null; Socket connection = null; InputStream input; try { server = new ServerSocket(fileGetPort, 100); while (running) { connection = server.accept(); /*your code*/ connection.close(); } } catch (IOException e) { e.printStackTrace(); } } }用的時候這樣就行啦
chatRun = new runChatServer(); JOptionPane.showMessageDialog(null, "running is " + chatRun.running); chatRun.start();
端口如果不關閉的話,會很痛苦,到後期你就得不斷尋找可用的端口 = =
怎麼關閉端口呢?
/* * 如果没有这个函数,很多端口都会被占用而影响我的心情!!! */ protected void processWindowEvent(WindowEvent e) { if (e.getID() == WindowEvent.WINDOW_CLOSING) { stopRun(chatRun); stopRun(fileRun); System.exit(0); } }其中的stopRun()
private class MyThread extends Thread { public boolean running = true; } private void stopRun(MyThread t) { if (t != null) { t.running = false; t.interrupt(); } }
介绍下 两个牛逼东西,用来将 int char 等 转化成byte[]
/* * 第一部份 写文件名字长度int 写第一个包的标志chat */ ByteArrayOutputStream boutput = new ByteArrayOutputStream(); DataOutputStream doutput = new DataOutputStream(boutput); doutput.writeChar('@'); byte[] flag = boutput.toByteArray(); all[0] = flag[0]; all[1] = flag[1]; ByteArrayOutputStream boutput2 = new ByteArrayOutputStream(); DataOutputStream doutput2 = new DataOutputStream(boutput2); doutput2.writeInt(nameLen); byte[] buf = boutput2.toByteArray();
JAVA API:
ByteArrayOutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()
和toString()
获取数据。
关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
DataOutputStream
数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
ByteArrayInputStream bintput = new ByteArrayInputStream(int_temp); DataInputStream dintput = new DataInputStream(bintput); int nameLen = dintput.readInt();JAVA API:
ByteArrayInputStream
ByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read
方法要提供的下一个字节。
关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
ByteArrayInputStream(byte[] buf)
创建一个 ByteArrayInputStream
,使用 buf
作为其缓冲区数组。
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
DataInputStream 对于多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。
read(byte[] b)
b
中。
現在貼上全部代碼,代碼部份有一些對話框出現主要是爲了調試用的。。
package ouyang; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.util.Arrays; public class MyQQ { public static void main(String args[]) { QQFrame frame = new QQFrame(); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } class QQFrame extends JFrame { /* * 假如配置文件不存在还是没问题的。 初始化的好处。。。 */ int targetChatPort = 5555; int chatGetPort = 6666; int targetFilePort = 7777; int fileGetPort = 8888; String targetIPAddress = "127.0.0.1"; public QQFrame() { QQPanel panel = new QQPanel(); setTitle("MyQQ"); setSize(600, 700); add(panel); } class QQPanel extends JPanel implements ActionListener { JMenuBar menuBar; JMenu firstMenu; JMenuItem settingItem; JMenuItem exitItem; JTextField nickNameField; JTextArea chatArea; JTextArea sendArea; JButton sendFileButton; JButton getFileButton; JButton sendMsgButton; JLabel sendLabel; JLabel chatLabel; JLabel nickNameLabel; JScrollPane sendScroll; JScrollPane chatScroll; boolean isRun; runChatServer chatRun = null; runFileServer fileRun = null; File sendFile; File getFile; GridBagLayout bag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); private boolean getOrNot = false; public QQPanel() { menuBar = new JMenuBar(); firstMenu = new JMenu("System"); settingItem = new JMenuItem("Setting"); exitItem = new JMenuItem("Exit"); firstMenu.add(settingItem); firstMenu.add(exitItem); menuBar.add(firstMenu); setJMenuBar(menuBar); sendArea = new JTextArea(10, 40); chatArea = new JTextArea(5, 40); sendScroll = new JScrollPane(sendArea); chatScroll = new JScrollPane(chatArea); sendFileButton = new JButton("SendFile"); getFileButton = new JButton("GetFile"); sendMsgButton = new JButton("Send"); sendLabel = new JLabel("Send Area:"); chatLabel = new JLabel("Chat Area:"); nickNameLabel = new JLabel("Nickname:"); nickNameField = new JTextField(20); chatScroll = new JScrollPane(chatArea); sendScroll = new JScrollPane(sendArea); chatScroll .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); chatScroll .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); sendScroll .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); sendScroll .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); setLayout(bag); setCons(0, 0, 1, 1); add(sendLabel, c); setCons(0, 1, 3, 3); add(sendScroll, c); setCons(0, 5, 1, 1); add(nickNameLabel, c); setCons(1, 5, 1, 1); add(nickNameField, c); setCons(0, 6, 1, 1); add(chatLabel, c); setCons(0, 7, 3, 3); add(chatScroll, c); setCons(0, 11, 1, 1); add(sendFileButton, c); setCons(1, 11, 1, 1); add(getFileButton, c); getFileButton.setEnabled(false); setCons(2, 11, 1, 1); add(sendMsgButton, c); initPort(); addListener(); } public void setCons(int x, int y, int width, int height) { c.weightx = 1; c.weighty = 1; c.gridheight = height; c.gridwidth = width; c.gridx = x; c.gridy = y; } public void initPort() { try { File settingFile = new File("d://setting.txt"); if (settingFile.exists()) { BufferedReader in = new BufferedReader(new FileReader( "d://setting.txt")); chatGetPort = Integer.parseInt(in.readLine()); fileGetPort = Integer.parseInt(in.readLine()); targetIPAddress = in.readLine(); targetChatPort = Integer.parseInt(in.readLine()); targetFilePort = Integer.parseInt(in.readLine()); System.out.println("chatGetPort:" + chatGetPort + "\n" + "fileGetPort:" + fileGetPort + "\n" + "targetIPAddress:" + targetIPAddress + "\n" + "targetChatPort:" + targetChatPort + "\n" + "targetFilePort:" + targetFilePort); } else { JOptionPane.showMessageDialog(null, "setting.txt不存在"); } } catch (IOException e) { } } public void addListener() { settingItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { SettingFrame f = new SettingFrame(); } }); exitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("我结束了..."); isRun = false; System.exit(0); } }); sendMsgButton.addActionListener(this); sendFileButton.addActionListener(this); getFileButton.addActionListener(this); // stopRun(chatRun); chatRun = new runChatServer(); JOptionPane .showMessageDialog(null, "running is " + chatRun.running); chatRun.start(); fileRun = new runFileServer(); JOptionPane .showMessageDialog(null, "running is " + chatRun.running); fileRun.start(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == sendMsgButton) { runChatClient(); String temp = nickNameField.getText() + ":" + chatArea.getText() + "\n"; sendArea.append(temp); chatArea.setText(null); } if (e.getSource() == sendFileButton) { JFileChooser chooser = new JFileChooser(); int returnVal = chooser.showSaveDialog(null); if (returnVal == JFileChooser.APPROVE_OPTION) { sendFile = chooser.getSelectedFile(); JOptionPane.showMessageDialog(null, "Your sendFile is " + sendFile.getName()); runFileClient(); } } if (e.getSource() == getFileButton) { getOrNot = true; } } /* * 如果没有这个函数,很多端口都会被占用而影响我的心情!!! */ protected void processWindowEvent(WindowEvent e) { if (e.getID() == WindowEvent.WINDOW_CLOSING) { stopRun(chatRun); stopRun(fileRun); System.exit(0); } } public void runChatClient() { Socket client; OutputStream output; try { client = new Socket("127.0.0.1", targetChatPort); System.out.println("Client is coming..\n"); System.out.println("Create socket..\n"); JOptionPane.showMessageDialog(null, "client coming... "); output = client.getOutputStream(); System.out.println("Create output stream..."); byte[] msg = (nickNameField.getText() + ":" + chatArea .getText()).getBytes(); output.write(msg); output.flush(); client.close(); } catch (IOException e) { System.out.println(e); } } public void runFileClient() { Socket client; OutputStream output; try { client = new Socket("127.0.0.1", targetFilePort); System.out.println("File Client is coming..\n"); System.out.println("Create file socket..\n"); JOptionPane.showMessageDialog(null, "file client coming... "); output = client.getOutputStream(); System.out.println("Create output stream..."); int fileLen = (int) sendFile.length(); byte name[] = sendFile.getName().getBytes("utf-8"); int nameLen = name.length; /* * 最后的两个字节是标志位,用来判断是不是最后一个包 那最后第三到第六四个字节是存放一个int型变量,表示文件名的长度 */ int allLen = fileLen + nameLen + 4 + 2; byte[] all = new byte[allLen]; byte[] file = new byte[fileLen]; /* * 第一部份 写文件名字长度int 写第一个包的标志chat */ ByteArrayOutputStream boutput = new ByteArrayOutputStream(); DataOutputStream doutput = new DataOutputStream(boutput); doutput.writeChar('@'); byte[] flag = boutput.toByteArray(); all[0] = flag[0]; all[1] = flag[1]; ByteArrayOutputStream boutput2 = new ByteArrayOutputStream(); DataOutputStream doutput2 = new DataOutputStream(boutput2); doutput2.writeInt(nameLen); byte[] buf = boutput2.toByteArray(); JOptionPane.showMessageDialog(null, "file length: " + buf.length); for (int i = 0; i < buf.length; i++) { all[2 + i] = buf[i]; } /* 第二部分 写入文件名字 */ for (int i = 0; i < name.length; i++) { all[4 + 2 + i] = name[i]; } /* 第三部分 写入文件内容 */ RandomAccessFile in = new RandomAccessFile(sendFile, "rw"); in.read(file); for (int i = 0; i < sendFile.length(); i++) { all[2 + 4 + nameLen + i] = file[i]; } output.write(all); output.flush(); client.close(); } catch (IOException e) { System.out.println(e); System.out.println("IP:" + "127.0.0.1" + "ERROR PORT:" + targetFilePort); } } private class MyThread extends Thread { public boolean running = true; } private void stopRun(MyThread t) { if (t != null) { t.running = false; t.interrupt(); } } private class runChatServer extends MyThread { public void run() { ServerSocket server = null; Socket connection = null; InputStream input; JOptionPane.showMessageDialog(null, "chat running is " + running); try { server = new ServerSocket(chatGetPort, 100); while (running) { JOptionPane.showMessageDialog(null, "server is coming"); connection = server.accept(); System.out.println("Connection received...\n"); JOptionPane.showMessageDialog(null, "Connection received"); System.out.println("Sending data...\n"); input = connection.getInputStream(); byte[] msg = new byte[512]; input.read(msg); String temp = new String(msg); sendArea.append(temp + "\n"); connection.close(); System.out .println("Transmission complete.Closing socket..\n"); } } catch (IOException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "chat server is missing"); } } } private class runFileServer extends MyThread { public void run() { ServerSocket server = null; Socket connection = null; InputStream input; try { server = new ServerSocket(fileGetPort, 100); JOptionPane.showMessageDialog(null, "file running is " + running); while (running) { JOptionPane.showMessageDialog(null, "file server is coming"); connection = server.accept(); getFileButton.setEnabled(true); while (true) { if (getOrNot == false) continue; else break; } JOptionPane.showMessageDialog(null, "Connection received"); System.out.println("Sending data...\n"); input = connection.getInputStream(); // String s=new String("Connection successful.\n"); byte[] tempBytes = new byte[60000000]; int length = input.read(tempBytes); JOptionPane.showMessageDialog(null, "接受长度为:" + length); if (length != -1) { char flag = '@'; ByteArrayOutputStream boutput = new ByteArrayOutputStream(); DataOutputStream doutput = new DataOutputStream( boutput); doutput.writeChar(flag); byte[] buf = boutput.toByteArray(); /* 标志位符合,没错,是第一个包 */ if (buf[0] == tempBytes[0] && buf[1] == tempBytes[1]) { byte[] firstbag = new byte[length]; for (int i = 0; i < length; i++) { firstbag[i] = tempBytes[i]; } /* 解析第一部分,原理是一个chat占2个字节int占4个字节 */ // byte char_temp[]=new byte[2]; byte int_temp[] = new byte[4]; for (int i = 0; i < 4; i++) int_temp[i] = firstbag[i + 2]; ByteArrayInputStream bintput = new ByteArrayInputStream( int_temp); DataInputStream dintput = new DataInputStream( bintput); int nameLen = dintput.readInt(); JOptionPane.showMessageDialog(null, "Part 3 complete... name's len:" + nameLen); /* 解析第二部分 */ byte name_temp3[] = new byte[nameLen]; for (int i = 0; i < nameLen; i++) { name_temp3[i] = firstbag[6 + i]; } String ch_name = new String(name_temp3, "UTF-8"); JOptionPane.showMessageDialog(null, "Part 2 complete... name::" + ch_name); System.out.println("名字为:" + ch_name); File tt = new File("D:\\downloads"); if (!tt.exists()) { JOptionPane .showMessageDialog(null, "文件不存在"); stopRun(fileRun); } getFile = new File(tt.getPath(), ch_name); JOptionPane.showMessageDialog( null, "getFile complete...file:" + getFile.getPath()); /* 解析第一部分 */ byte[] file = new byte[length - nameLen - 6]; for (int i = 0; i < length - nameLen - 6; i++) { file[i] = firstbag[6 + nameLen + i]; } RandomAccessFile out = new RandomAccessFile( getFile, "rw"); out.write(file); out.close(); JOptionPane.showMessageDialog(null, "Part 1 's firstbag complete..."); } /* 不是第一个包啊 */ else { JOptionPane.showMessageDialog(null, "Part 1 's leftbag begin..."); RandomAccessFile out = new RandomAccessFile( getFile, "rw"); out.write(tempBytes); out.close(); } } getFileButton.setEnabled(false); getOrNot = false; connection.close(); } } catch (IOException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "file server is missing"); } } } } class SettingFrame extends JFrame { JTextField targetChatPortField; JTextField chatGetPortField; JTextField targetFilePortField; JTextField fileGetPortField; JTextField targetIPAddressField; JLabel targetChatPortLabel; JLabel targetFilePortLabel; JLabel chatGetPortLabel; JLabel fileGetPortLabel; JLabel targetIPAddressLabel; JButton yes, no; GridBagLayout bag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); public void setCons(int x, int y, int width, int height) { c.gridheight = height; c.gridwidth = width; c.gridx = x; c.gridy = y; c.weightx = 1; c.weighty = 1; } public SettingFrame() { targetChatPortField = new JTextField(10); chatGetPortField = new JTextField(10); targetFilePortField = new JTextField(10); fileGetPortField = new JTextField(10); targetIPAddressField = new JTextField(10); targetChatPortLabel = new JLabel("目标文本端口"); targetFilePortLabel = new JLabel("目标文件端口"); chatGetPortLabel = new JLabel("接收文本端口"); fileGetPortLabel = new JLabel("接收文件端口"); targetIPAddressLabel = new JLabel("目标接收地址"); yes = new JButton("确定"); no = new JButton("取消"); JPanel panel = new JPanel(); setLayout(bag); setCons(0, 0, 1, 1); add(chatGetPortLabel, c); setCons(1, 0, 1, 1); add(chatGetPortField, c); setCons(0, 1, 1, 1); add(fileGetPortLabel, c); setCons(1, 1, 1, 1); add(fileGetPortField, c); setCons(0, 2, 1, 1); add(targetIPAddressLabel, c); setCons(1, 2, 1, 1); add(targetIPAddressField, c); setCons(0, 3, 1, 1); add(targetChatPortLabel, c); setCons(1, 3, 1, 1); add(targetChatPortField, c); setCons(0, 4, 1, 1); add(targetFilePortLabel, c); setCons(1, 4, 1, 1); add(targetFilePortField, c); setCons(0, 5, 1, 1); add(yes, c); setCons(1, 5, 1, 1); add(no, c); this.setVisible(true); // this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 千萬不能加這句 this.setTitle("Setting..."); this.setSize(300, 200); init(); new doSetting().run(); } public void init() { yes.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { new doSetting().reFlashSettingFile(); JOptionPane.showMessageDialog(null, "配置文件更新成功"); dispose(); /* 这个dispose()没见过,找了好久才找到 */ } }); no.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { dispose(); } }); } class doSetting extends Thread { public void run() { try { File settingFile = new File("d://setting.txt"); if (settingFile.exists()) { BufferedReader in = new BufferedReader(new FileReader( settingFile)); chatGetPortField.setText(in.readLine()); fileGetPortField.setText(in.readLine()); targetIPAddressField.setText(in.readLine()); targetChatPortField.setText(in.readLine()); targetFilePortField.setText(in.readLine()); } } catch (IOException e) { System.out.println("setting file is error~~"); } } public void reFlashSettingFile() { try { PrintWriter out = new PrintWriter(new FileOutputStream( "d://setting.txt"), true); out.println(chatGetPortField.getText()); out.println(fileGetPortField.getText()); out.println(targetIPAddressField.getText()); out.println(targetChatPortField.getText()); out.println(targetFilePortField.getText()); } catch (IOException e) { System.out.println("reflash setting is error~~~"); } } } } }