哈工大 java实验4 基于socket的消息发送与文件传输

来源:互联网 发布:知乎客户端无法登陆 编辑:程序博客网 时间:2024/06/05 18:28

这次试验比较难,套接字这东西不好调试,很蛋疼。

首先是套接字,java的套接字封装的比较好,简单易用。

客户端这样写:

try {Socket socket = new Socket(IP_Address,Port);BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));BufferedWriter socketWrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));socketWrite.write("yourString");socketWrite.flush();} catch (UnknownHostException e1) {System.out.println("Error setting up socket connection: unknown host at "+ IP_Address + ":" +Port);} catch (IOException e2) {System.out.println("Error setting up socket connection: "+ e);}

异常抛出的时候,输出个字符串,有益于调试。

关于这个BufferedReader的封装,

在java里inputStream,outputStream这类的东西,一般用来处理8位的流,ASCII,字符,二进制,一般用这个

Reader,Writer用来处理16位的流,就是Unicode之类的。

而且有一个,InputStreamReader,OutStreamReader 负责二者之间的转换。

其中我经常用这个 BufferedReader 和 这个 DataInputStream,后者有getInt()之类的方法比较好用。

服务端这样写

public void run() {try {server = new ServerSocket(textReceivePort);while (running) {                                 //线程运行时在外部吧running改成false可终止线程运行System.out.println("inThread!");incomingConnection = server.accept();System.out.println("HaveAccept!");BufferedReader socketReader = new BufferedReader(new InputStreamReader(incomingConnection.getInputStream()));String t;t = socketReader.readLine();if (t != null)chatArea.append(t + "\n");socketReader.close();System.out.println("message up!");}} catch (BindException e) {System.out.println("Unable to bind to port "+ textReceivePort);} catch (IOException e) {System.out.println("Unable to instantiate a ServerSocket on port: "+ textReceivePort);}}

重点是不要忘记停掉不用的线程。。。。。。。。不然会出现好几十个线程在跑,占用一大堆端口的情况。

平常只要把running设成false,让线程自己跑完就可以了,

执行server.accept这一句时,线程会原地等待,这时候想终止线程,需要调用,interrupt()方法使线程抛出异常而停止。

stop()方法已经被弃用了,最好不要使用,关于为什么弃用,核心技术上有详细讲解。


布局方面,需要一个菜单栏,java提供了相关的类,很轻松就可以写好

JMenuBar menuBar = new JMenuBar();JMenu sysMenu = new JMenu("System");JMenuItem Item_Setting = new JMenuItem("Setting");JMenuItem Item_Exit = new JMenuItem("Exit");Item_Setting.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent event) {}});Item_Exit.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent event) {}});sysMenu.add(Item_Setting);sysMenu.add(Item_Exit);menuBar.add(sysMenu);setJMenuBar(menuBar);
设置界面我直接使用了另一个JFrame,在响应里把它设成可见就可以了。


最后关闭程序时,一定要把,所有的线程和套接字都关掉。

protected void processWindowEvent(WindowEvent e) {if (e.getID() == WindowEvent.WINDOW_CLOSING) {stopRun(messageRun);stopRun(fileRun);System.exit(0);}}

这样基本功能就都实现了,

不过,我发现在释放掉socket之后,他所绑定的端口不会立即被释放掉,调试的时候蛋疼了一阵,谁有解决方发请留言告知。

还有,我使用BufferedWriter,和,BufferedReader,实现传输文件时会因为编码格式不同而产生乱码,比如“UTF-8”的就正常,而“”GBK“的就是乱码。

大概用Stream按bytes传就不会有问题,不过懒得写了。


最后贴上源码

import java.awt.GridBagConstraints;import java.awt.GridBagLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowEvent;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.BindException;import java.net.ServerSocket;import java.net.Socket;import java.net.UnknownHostException;import javax.swing.JButton;import javax.swing.JFileChooser;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.border.TitledBorder;public class MyQQ {public static void main(String[] args) {MF = new MainFrame();}private static class AbstractFrame extends JFrame {public AbstractFrame(String name) {super(name);}protected void setCons(int x, int y, int z, int k) {cons.gridx = x;cons.gridy = y;cons.gridwidth = z;cons.gridheight = k;}protected void init() {cons.weightx = 1;cons.weighty = 1;}protected GridBagConstraints cons = new GridBagConstraints();}private static class MainFrame extends AbstractFrame implementsActionListener {@Overridepublic void actionPerformed(ActionEvent e) {Object source = e.getSource();if (source.equals(sentChat)) {try {System.out.println("inAction");Socket socket = new Socket(IP_Address, textSendPort);BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));BufferedWriter socketWrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));socketWrite.write(textNickName.getText() + ":"+ sendArea.getText() + "\n");socketWrite.flush();System.out.println(messageRun.getState());} catch (UnknownHostException e1) {System.out.println("Error setting up socket connection: unknown host at "+ IP_Address + ":" + textReceivePort);} catch (IOException e2) {System.out.println("Error setting up socket connection: "+ e);}} else if (source.equals(sentFile)) {JFileChooser fDialog = new JFileChooser();fDialog.setDialogTitle("Choose File To Send");int returnVal = fDialog.showOpenDialog(null);if (JFileChooser.APPROVE_OPTION == returnVal) {//receiveFile.setEnabled(true);try {Socket socket = new Socket(IP_Address, fileSendPort);srcFile = fDialog.getSelectedFile().getPath();fileName = fDialog.getSelectedFile().getName();File inFile = new File(srcFile);BufferedWriter socketWrite = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(inFile), "UTF-8"));System.out.println("chooesed file");char[] tempbytes = new char[1000];String tempbyte;fileRow = 0;while ((tempbyte = in.readLine()) != null) {fileRow++;System.out.println(tempbyte + "\n");socketWrite.write(tempbyte + "\r");socketWrite.flush();}System.out.println("W_row" + fileRow);in.close();socketWrite.close();socket.close();} catch (UnknownHostException e1) {System.out.println("Error setting up socket connection: unknown host at "+ IP_Address + ":" + textReceivePort);} catch (IOException e2) {System.out.println("Error setting up socket connection: When send file");}}} else if (source.equals(receiveFile)) {receiveFile.setEnabled(false);fileRun.hanging = false;}}private class MyThread extends Thread {public boolean running = true;public ServerSocket server;public Socket incomingConnection = null;boolean changePort = true;public boolean hanging = true;}private class MessageListener extends MyThread {@Overridepublic void run() {try {server = new ServerSocket(textReceivePort);while (running) {System.out.println("inThread!");incomingConnection = server.accept();System.out.println("HaveAccept!");BufferedReader socketReader = new BufferedReader(new InputStreamReader(incomingConnection.getInputStream()));String t;t = socketReader.readLine();if (t != null)chatArea.append(t + "\n");socketReader.close();System.out.println("message up!");}} catch (BindException e) {System.out.println("Unable to bind to port "+ textReceivePort);} catch (IOException e) {System.out.println("Unable to instantiate a ServerSocket on port: "+ textReceivePort);}}}private class FileListener extends MyThread {@Overridepublic void run() {try {server = new ServerSocket(fileReceivePort);while (running) {System.out.println("inThreadFile!");incomingConnection = server.accept();System.out.println("HaveFileAccept!");BufferedReader socketReader = new BufferedReader(new InputStreamReader(incomingConnection.getInputStream(),"UTF-8"));receiveFile.setEnabled(true);hanging = true;while (hanging) {}System.out.println("rece File~");File outFile = new File("DownLoad");BufferedWriter os = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));char[] tempbytes = new char[1000];String tempbyte;while ((socketReader.readLine())!=null) {tempbyte = socketReader.readLine();os.write(tempbyte);os.flush();}os.close();socketReader.close();}} catch (BindException e) {System.out.println("FileListener Unable to bind to port "+ fileReceivePort);} catch (IOException e) {System.out.println("Unable to instantiate a ServerSocket on port: "+ fileReceivePort);}}}public MainFrame() {super("Main");init();setLayout(new GridBagLayout());setCons(0, 0, 5, 5);add(chatArea, cons);setCons(0, 5, 1, 1);add(nickName, cons);setCons(1, 5, 4, 1);add(textNickName, cons);setCons(0, 6, 5, 3);add(sendArea, cons);setCons(0, 9, 2, 1);add(sentFile, cons);setCons(2, 9, 2, 1);add(receiveFile, cons);setCons(4, 9, 1, 1);add(sentChat, cons);setSize(300, 600);this.setVisible(true);}@Overrideprotected void processWindowEvent(WindowEvent e) {if (e.getID() == WindowEvent.WINDOW_CLOSING) {stopRun(messageRun);stopRun(fileRun);System.exit(0);}}protected void init() {super.init();upDate();FlashState();menuBar = new JMenuBar();sysMenu = new JMenu("System");Item_Setting = new JMenuItem("Setting");Item_Exit = new JMenuItem("Exit");Item_Setting.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent event) {SF = new SettingFrame();}});Item_Exit.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent event) {System.out.print("bbb");}});sysMenu.add(Item_Setting);sysMenu.add(Item_Exit);menuBar.add(sysMenu);setJMenuBar(menuBar);chatArea.setBorder(new TitledBorder(""));sendArea.setBorder(new TitledBorder(""));receiveFile.setEnabled(false);sentFile.addActionListener(this);receiveFile.addActionListener(this);sentChat.addActionListener(this);}public void FlashState() {upDateToFile();System.out.println("FlashState!");stopRun(messageRun);messageRun = new MessageListener();messageRun.start();stopRun(fileRun);fileRun = new FileListener();fileRun.start();}private void upDate() {File configFile = new File("ConfigFile.txt");if (configFile.exists()) {try {BufferedReader in = new BufferedReader(new FileReader(configFile));textReceivePort = Integer.parseInt(in.readLine());fileReceivePort = Integer.parseInt(in.readLine());textSendPort = Integer.parseInt(in.readLine());fileSendPort = Integer.parseInt(in.readLine());IP_Address = in.readLine();in.close();} catch (IOException e) {}} else {upDateToFile();}}private void upDateToFile() {File configFile = new File("ConfigFile.txt");try {BufferedWriter out = new BufferedWriter(new FileWriter(configFile));out.write(textReceivePort + "\r");out.write(fileReceivePort + "\r");out.write(textSendPort + "\r");out.write(fileSendPort + "\r");out.write(IP_Address + "\r");out.close();} catch (IOException e) {}}private void stopRun(MyThread t) {if (t != null) {t.running = false;t.changePort = false;t.hanging = false;t.interrupt();}}private MessageListener messageRun = null;private FileListener fileRun = null;private static String srcFile;private static String fileName = "downLoad";private static int fileRow;private JMenuBar menuBar;private JMenu sysMenu;private JMenuItem Item_Setting;private JMenuItem Item_Exit;private JTextArea chatArea = new JTextArea(10, 20);private JTextArea sendArea = new JTextArea(5, 20);private JLabel nickName = new JLabel("NickName:");private JTextField textNickName = new JTextField(15);private JButton sentFile = new JButton("SendFile");private JButton receiveFile = new JButton("receiveFile");private JButton sentChat = new JButton("send");}private static class SettingFrame extends AbstractFrame implementsActionListener {@Overridepublic void actionPerformed(ActionEvent e) {Object source = e.getSource();if (source.equals(submit)) {textReceivePort = Integer.parseInt(Text_1.getText());fileReceivePort = Integer.parseInt(Text_2.getText());String IP_Address = Text_3.getText();textSendPort = Integer.parseInt(Text_4.getText());fileSendPort = Integer.parseInt(Text_5.getText());dispose();MF.FlashState();} else if (source.equals(cancel)) {dispose();}}public SettingFrame() {super("Setting");init();setLayout(new GridBagLayout());// ----------------------------------------setCons(0, 0, 2, 1);add(label_1, cons);setCons(2, 0, 2, 1);add(Text_1, cons);// ----------------------------------------setCons(0, 1, 2, 1);add(label_2, cons);setCons(2, 1, 2, 1);add(Text_2, cons);// ----------------------------------------setCons(0, 2, 2, 1);add(label_3, cons);setCons(2, 2, 2, 1);add(Text_3, cons);// ----------------------------------------setCons(0, 3, 2, 1);add(label_4, cons);setCons(2, 3, 2, 1);add(Text_4, cons);// ----------------------------------------setCons(0, 4, 2, 1);add(label_5, cons);setCons(2, 4, 2, 1);add(Text_5, cons);// ----------------------------------------setCons(1, 5, 1, 1);add(submit, cons);setCons(2, 5, 1, 1);add(cancel, cons);// ----------------------------------------setSize(300, 300);this.setVisible(true);}protected void init() {super.init();submit.addActionListener(this);cancel.addActionListener(this);Text_1.setText(textReceivePort + "");Text_2.setText(fileReceivePort + "");Text_3.setText(IP_Address);Text_4.setText(textSendPort + "");Text_5.setText(fileSendPort + "");}private JLabel label_1 = new JLabel("Text Receive Port:");private JLabel label_2 = new JLabel("File Receive Port:");private JLabel label_3 = new JLabel("Send IP:");private JLabel label_4 = new JLabel("Text Send Port:");private JLabel label_5 = new JLabel("File Send Port:");private JTextField Text_1 = new JTextField(10);private JTextField Text_2 = new JTextField(10);private JTextField Text_3 = new JTextField(10);private JTextField Text_4 = new JTextField(10);private JTextField Text_5 = new JTextField(10);private JButton submit = new JButton("Submit");private JButton cancel = new JButton("Cancel");}private static MainFrame MF;private static SettingFrame SF;private static String IP_Address = "127.0.0.1";private static int textReceivePort = 5555;private static int fileReceivePort = 6666;private static int textSendPort = 5555;private static int fileSendPort = 6666;}