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

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

首先是套接字,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() {
				@Override
				public void actionPerformed(ActionEvent event) {
					
				}
			});
			Item_Exit.addActionListener(new ActionListener() {
				@Override
				public 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 implements
			ActionListener {
		@Override
		public 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 {
			@Override
			public 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 {
			@Override
			public 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);
		}

		@Override
		protected 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() {
				@Override
				public void actionPerformed(ActionEvent event) {
					SF = new SettingFrame();
				}
			});
			Item_Exit.addActionListener(new ActionListener() {
				@Override
				public 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 implements
			ActionListener {
		@Override
		public 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;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值