`

java socket 多线程实例

    博客分类:
  • java
阅读更多

 题:

做一个简单的网络控制软件,分为Server端和Client端,Server段填入一个有效的端口然后监听,Client端填入Server端的地址和端口号然后连接,连接以后双方可通信。

要求: server绑定端口大于9000,用单独的Server类和单独的Client类封装SocketServerSocket

               Client端发送命令start Server端, Server端返回欢迎信息“Hello! Start…”Client端, 同时Server端为这个Client端生成一个新的线程,这个线程每隔15秒发送一次Server端时间给Client端;

              Client端发送命令stop Server端, Server端停下线程,并返回先前SERVER端发送时间的次数和退出信息如:已发送时间次数为N次,bye bye”.

              Client端发送命令不是start stop Server端时, Server端返回信息如:命令未完定义,命令为XXXX”.

界面如下面两图所示:

 

 

服务器:

 

package cn.com.starit;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Event;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Date;
import java.util.HashMap;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

/**
 * 监控服务器
 */
public class ChatServer extends JFrame {
	private static final long serialVersionUID = -2557804639559633012L;

	private JFrame frame;
	private JLabel portLabel;
	private JTextField portField;
	private JButton listenButton;
	private JPanel contentPanel;
	private JScrollPane scrollPane;
	private DefaultListModel listModel;
	private JList infoArea;

	private static final int WIDTH = 400;
	private static final int HEIGHT = 300;

	private ServerSocket ss;
	private HashMap<ChatClient, Integer> sockets;
	private boolean started = false;// 服务器启动标志

	// 构造方法
	public ChatServer() {
	}

	public void init() {
		// 窗口服务器窗口
		frame = new JFrame("服务器");
		frame.setResizable(false);
		// 设置窗口居中
		int screenWidth = (int) java.awt.Toolkit.getDefaultToolkit()
				.getScreenSize().getWidth();
		int screenHeight = (int) java.awt.Toolkit.getDefaultToolkit()
				.getScreenSize().getHeight();
		frame.setBounds((screenWidth - WIDTH) / 2, (screenHeight - HEIGHT) / 2,
				WIDTH, HEIGHT);

		contentPanel = (JPanel) frame.getContentPane();
		contentPanel.setLayout(null);

		portLabel = new JLabel("端口:");
		portField = new JTextField(10);
		listenButton = new JButton("监听");
		listModel = new DefaultListModel();
		infoArea = new JList(listModel);
		scrollPane = new JScrollPane(infoArea);
		listModel.addElement("#服务器消息");
		new Scroller().start();
		infoArea.setBackground(Color.YELLOW);
		portLabel.setBounds(new Rectangle(40, 10, 50, 20));
		portField.setBounds(new Rectangle(100, 10, 100, 20));

		JPanel panel = new JPanel(new BorderLayout());
		JPanel panel1 = new JPanel(new BorderLayout());
		panel.add(listenButton, BorderLayout.CENTER);
		panel.setBounds(new Rectangle(220, 10, 60, 20));
		panel1.setBounds(new Rectangle(290, 10, 60, 20));

		scrollPane.setBounds(18, 50, 355, 200);
		contentPanel.add(portLabel, null);
		contentPanel.add(portField, null);
		contentPanel.add(panel, null);
		contentPanel.add(scrollPane, null);
		// 设置窗口可见
		frame.setVisible(true);

		// 注册监听按钮的鼠标事件
		listenButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				String portStr = portField.getText();
				try {
					int port = Integer.valueOf(portStr);
					if (port < 9000 || port > 65535) {
						JOptionPane.showMessageDialog(null,
						"端口为不小于9000且不大于65535的整数,请正确的输入!");
						return;
					} else {
						createServer(port);
						new Receiver().start();
					}
				} catch (NumberFormatException e1) {
					JOptionPane.showMessageDialog(null,
					"端口为不小于9000且不大于65535的整数,请正确的输入!");
					return;
				}
			}
		});

		//
		portField.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == Event.ENTER) {
					String portStr = portField.getText();
					int port = Integer.valueOf(portStr);
					if (port < 9000 || port > 65535) {
						JOptionPane.showMessageDialog(null,
								"端口为不小于9000且不大于65535的整数,请正确的输入!");
						return;
					} else {
						createServer(port);
						new Receiver().start();
					}
				}
			}
		});

		// 注册窗口关闭事件
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				if (ss != null && !ss.isClosed()) {
					stopServer();
					System.out.println("#服务器已经关闭");
					listModel.addElement("#服务器已经关闭");
				}
				dispose();
				System.exit(0);
			}
		});
	}

	// 创建监听
	public void createServer(int port) {
		try {
			ss = new ServerSocket(port);
			sockets = new HashMap<ChatClient, Integer>();
			started = true;
			System.out.println("#服务器启动成功");
			listModel.addElement("#服务器启动成功");
			portField.setText("");
		}catch (IllegalArgumentException e) {
			listModel.addElement("#服务器启动失败,端口允许范围9000~65535");
			System.out.println("#服务器启动失败");
		} catch (IOException e) {
			System.out.println("#服务器启动失败");
			e.printStackTrace();
		}
	}

	// 关闭服务
	public void stopServer() {
		try {
			if (ss != null) {
				started = false;
				ss.close();
				ss = null;
				dispose();
			}
		} catch (IOException e) {
			System.out.println("#服务器关闭失败");
			e.printStackTrace();
		}
	}

	// 开启一个线程用来接收客户端的连接
	class Receiver extends Thread {

		@Override
		public void run() {
			while (started) {
				try {
					Socket s = ss.accept();
					ChatClient client = new ChatClient();
					client.setSocket(s);
					client.setStart(false);
					sockets.put(client, 0);
					String remoteSocketAddress = client.getSocket()
							.getRemoteSocketAddress().toString();
					int start = remoteSocketAddress.indexOf("/") + 1;
					int end = remoteSocketAddress.indexOf(":");
					listModel.addElement("#CLIENT端为"
							+ remoteSocketAddress.substring(start, end)
							+ "连接成功……");
					DataOutputStream dos = new DataOutputStream(client
							.getSocket().getOutputStream());
					dos.writeUTF("#连接成功");
					new CommandReceiver(client).start();
				} catch (SocketException e) {

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

	// 负责接受客户端命令的线程类
	class CommandReceiver extends Thread {
		private ChatClient client;
		private DataInputStream bis;
		private DataOutputStream dos;
		private Thread thread;
		private boolean flag = true;

		public CommandReceiver(ChatClient client) {
			this.client = client;
			try {
				bis = new DataInputStream(client.getSocket().getInputStream());
				dos = new DataOutputStream(client.getSocket().getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			while (flag) {
				try {
					String command = bis.readUTF();
					if (command.equals("start")) {
						client.setStart(true);
						ChatThread ct = new ChatThread(client);
						thread = new Thread(ct);
						thread.start();
					} else if (command.equals("stop")) {
						if (thread != null) {
							client.setStart(false);
							String remoteSocketAddress = client.getSocket()
									.getRemoteSocketAddress().toString();
							int start = remoteSocketAddress.indexOf("/") + 1;
							int end = remoteSocketAddress.indexOf(":");
							listModel.addElement("#CLIENT端为"
									+ remoteSocketAddress.substring(start, end)
									+ "停止发送时间……");
							dos.writeUTF("#已发送时间次数为" + sockets.get(client)
									+ "次:BYE-BYE!!!!");
							// 重置发送时间次数
							sockets.put(client, 0);
						} else {
							dos.writeUTF("#start命令尚未执行……");
						}
					} else {
						dos.writeUTF("#命令未完定义,命令为" + command);
					}
				} catch (SocketException e) {
					String remoteSocketAddress = client.getSocket()
							.getRemoteSocketAddress().toString();
					int start = remoteSocketAddress.indexOf("/") + 1;
					int end = remoteSocketAddress.indexOf(":");
					System.out.println("#客户端"
							+ remoteSocketAddress.substring(start, end) + "关闭");
					flag = false;
					client.setStart(false);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 负责发送时间的线程类
	class ChatThread implements Runnable {

		private ChatClient client;
		private DataOutputStream dos;

		public ChatThread(ChatClient client) {
			this.client = client;
			try {
				dos = new DataOutputStream(client.getSocket().getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@SuppressWarnings("deprecation")
		public void run() {
			while (client.isStart()) {
				try {
					String remoteSocketAddress = client.getSocket()
							.getRemoteSocketAddress().toString();
					int start = remoteSocketAddress.indexOf("/") + 1;
					int end = remoteSocketAddress.indexOf(":");
					listModel.addElement("#CLIENT端为"
							+ remoteSocketAddress.substring(start, end)
							+ ",开始同步时间……");
					String msg = "#当前时间:" + new Date().toLocaleString();
					dos.writeUTF(msg);
					int count = sockets.get(client).intValue() + 1;
					sockets.put(client, count);
					Thread.sleep(8000);
				} catch (IOException e1) {
					e1.printStackTrace();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 负责滚动的线程
	class Scroller extends Thread {
		@Override
		public void run() {
			while (true) {
				scrollToView();
			}
		}
	}

	// Jlist的滚动方法
	private void scrollToView() {
		int lastIndex = listModel.getSize();
		Rectangle rect = infoArea.getCellBounds(lastIndex - 1, lastIndex - 1);
		scrollPane.getViewport().scrollRectToVisible(rect);
	}

	public static void main(String[] args) {
		new ChatServer().init();
	}

}

 

 

客户端:

package cn.com.starit;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Event;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

/**
 * 客户端
 */
public class ChatClient extends JFrame{

	private static final long serialVersionUID = -8536844369570721300L;

	private Socket socket;
	private DataInputStream bis;
	private DataOutputStream dos;
	private JFrame frame;
	private JPanel centerPanel;
	private JPanel buttonPanel1;
	private JPanel buttonPanel2;
	private JLabel addressLabel;
	private JLabel portLabel;
	private JTextField addressField;
	private JTextField portField;
	private JButton linkButton;
	private JLabel msg1;
	private JLabel msg2;
	private DefaultListModel listModel;
	private JScrollPane scrollPane;
	private JList msgArea1;
	private JTextField msgField;
	private JButton sendButton;
	
	private static final int WIDTH = 400;
	private static final int HEIGHT = 400;
	private boolean connected = false;
	private boolean start;
	
	//初始化客户端窗口
	public void init(){
		//创建客户端窗口
		frame = new JFrame("客户端");
		frame.setResizable(false);
		int screenWidth = (int) java.awt.Toolkit.getDefaultToolkit().getScreenSize().getWidth();
		int screenHeight = (int) java.awt.Toolkit.getDefaultToolkit().getScreenSize().getHeight();
		frame.setBounds((screenWidth-WIDTH)/2, (screenHeight-HEIGHT)/2, WIDTH, HEIGHT);
		
		addressLabel =  new JLabel("地址:");
		portLabel = new JLabel("端口:");
		addressField = new JTextField(10);
		portField = new JTextField(10);
		linkButton = new JButton("连接");
		msg1 = new JLabel("接收的消息:");
		msg2 = new JLabel("发送的消息:");
		listModel = new DefaultListModel();
		msgArea1 = new JList(listModel);
		scrollPane = new JScrollPane(msgArea1);
		listModel.addElement("#客户端消息:");
		new Scroller().start();
		msgArea1.setBackground(Color.YELLOW);
		msgField = new JTextField(25);
		sendButton = new JButton("发送");
		buttonPanel1 = new JPanel(new BorderLayout());
		buttonPanel2 = new JPanel(new BorderLayout());
		
		addressLabel.setBounds(new Rectangle(10,10,40,20));
		addressField.setBounds(new Rectangle(50,10,100,20));
		portLabel.setBounds(new Rectangle(160,10,40,20));
		portField.setBounds(new Rectangle(200,10,80,20));
		buttonPanel1.setBounds(new Rectangle(290,10,60,20));
		buttonPanel1.add(linkButton,BorderLayout.CENTER);
		msg1.setBounds(new Rectangle(10,50,350,20));
		scrollPane.setBounds(new Rectangle(10,80,372,200));
		msg2.setBounds(new Rectangle(10,290,350,20));
		msgField.setBounds(new Rectangle(10,320,280,20));
		buttonPanel2.setBounds(new Rectangle(300,320,60,20));
		buttonPanel2.add(sendButton,BorderLayout.CENTER);
		
		
		centerPanel = (JPanel) frame.getContentPane();
		centerPanel.setLayout(null);
		
		centerPanel.add(addressLabel);
		centerPanel.add(addressField);
		centerPanel.add(portLabel);
		centerPanel.add(portField);
		centerPanel.add(buttonPanel1);
		centerPanel.add(msg1);
		centerPanel.add(scrollPane);
		centerPanel.add(msg2);
		centerPanel.add(msgField);
		centerPanel.add(buttonPanel2);
		
		// 设置窗口可见
		frame.setVisible(true);
		
		//注册连接按钮的鼠标事件
		linkButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				String address = addressField.getText();
				String portStr = portField.getText();
				int port = Integer.valueOf(portStr);
				Pattern addressPattern = Pattern.compile("^\\d+\\.\\d+\\.\\d+\\.\\d+$");
				Matcher addressMatcher = addressPattern.matcher(address);
				if(!addressMatcher.matches()){
					JOptionPane.showMessageDialog(null, "Ip地址输入的格式不正确!");
					return;
				}else if(port<9000 || port>65535){
					JOptionPane.showMessageDialog(null, "端口为不小于9000且不大于65535的整数,请正确的输入!");
					return;
				}else{
					link(address,port);
				}
			}
		});
		//注册发送按钮的鼠标事件
		sendButton.addMouseListener(new MouseAdapter(){
			@Override
			public void mouseClicked(MouseEvent e) {
				String command = msgField.getText().trim();
				if(command!=null && !command.equals("")){
					sendMsg(command);
				}
				msgField.setText("");
			}
		});
		
		//注册窗口事件
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				dispose();
				System.exit(0);
			}
		});
		
		//注册回车事件
		msgField.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode()==Event.ENTER){
					String command = msgField.getText().trim();
					if(command!=null && !command.equals("")){
						sendMsg(command);
					}
					msgField.setText("");
				}
			}
		});
	}
	
	//创建连接
	public void link(String address,int port){
		try {
			socket = new Socket(address,port);
			connected = true;
			bis = new DataInputStream(socket.getInputStream());
			dos = new DataOutputStream(socket.getOutputStream());
			new Receiver().start();
			addressField.setText("");
			portField.setText("");
		}catch (ConnectException e) {
			System.out.println("#无法连接服务器,请检查端口是否填写正确!");
			listModel.addElement("#无法连接服务器,请检查端口是否填写正确!");
		}catch (UnknownHostException e) {
			System.out.println("#无法连接服务器,请检查地址是否填写正确!");
			listModel.addElement("#无法连接服务器,请检查地址是否填写正确!");
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//发消息
	public void sendMsg(String msg){
		try {
			dos.writeUTF(msg);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//接受消息
	public String receiveMsg(){
		String msg;
		try {
			msg = bis.readUTF();
			return msg;
		}catch (SocketException e) {
			connected = false;
			System.out.println("#服务器已经关闭");
			listModel.addElement("#服务器已经关闭");
			return null;
		}catch (IOException e) {
			return null;
		}
	}
	
	//接受消息的线程类
	class Receiver extends Thread{
		public void run() {
			while(connected){
				String msg = receiveMsg();
				if(msg!=null && !msg.equals("")){
					listModel.addElement(msg);
				}
			}
		}
	}
	

	
	public boolean isStart() {
		return start;
	}

	public void setStart(boolean start) {
		this.start = start;
	}
	
	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	//负责滚动的线程
	class Scroller extends Thread{
		@Override
		public void run() {
			while(true){
				scrollToView();
			}
		}
	}
	
	//Jlist的滚动方法
	 private void scrollToView(){
	        int lastIndex = listModel.getSize();
	        Rectangle rect=msgArea1.getCellBounds(lastIndex-1,lastIndex-1);
	        scrollPane.getViewport().scrollRectToVisible(rect);
	    }
	
	public static void main(String[] args) {
		new ChatClient().init();
	}
}

 

  • 大小: 7.8 KB
  • 大小: 11.4 KB
分享到:
评论

相关推荐

    Java Socket多线程实例及文档

    对于"Java Socket多线程实例",可能是更复杂的多线程Socket应用案例,可能涵盖了更丰富的功能,例如线程池管理、心跳检测、超时处理等高级话题。 六、结论 Java Socket与多线程的结合是构建高效网络服务器的关键...

    java Socket 多线程

    总结来说,Java Socket多线程是构建高并发网络服务的关键技术。通过合理地设计和实现,可以有效地提升服务器的并发处理能力,为用户提供更高效的服务。在实际项目中,应根据具体需求选择适合的线程模型,例如线程池...

    java socket多线程文件传输实例项目

    Java Socket多线程文件传输实例项目是一个典型的网络编程应用场景,主要涉及了Socket编程、多线程处理以及文件I/O操作等关键知识点。在这个项目中,开发者利用Java的Socket API实现了一个能够支持多个客户端同时进行...

    java socket多线程文件上传下载实例项目

    Java Socket多线程文件上传下载实例项目是一种基于Java网络编程技术实现的,旨在处理大量并发连接的文件传输服务。在本项目中,Socket是客户端与服务器之间通信的基础,它允许两个应用程序通过网络交换数据。多线程...

    java Socket多线程通讯实例

    总结起来,Java Socket多线程通讯实例展示了如何利用Java的网络编程API实现TCP通信,并通过多线程处理并发连接,这在构建例如QQ这样的聊天应用时是非常重要的技术。通过这种方式,服务端能够有效地管理大量并发的...

    java socket多线程多人聊天室

    本项目"java socket多线程多人聊天室"旨在利用Java的Socket API创建一个支持多个客户端同时连接的聊天环境。在这个项目中,主要涉及三个关键组件:Server(服务器)、Client(客户端)和User(用户)。 首先,`...

    java socket多线程通信案例

    基于多线程实现的JavaSocket客户端-服务端点对点异步通信程序代码

    Java Socket实例(服务器多线程)

    在这个实例中,我们关注的是服务器端的多线程应用,这在处理多个并发连接时尤其有用。多线程允许服务器同时处理多个客户端请求,提高系统效率和响应速度。 在Java中,Socket类代表一个网络连接,ServerSocket类用于...

    java socket 多线程通讯示例

    总的来说,Java Socket多线程通信是一种强大的工具,用于构建分布式系统和网络应用。理解如何创建和管理Socket连接,以及如何在多线程环境下处理这些连接,是成为熟练的Java网络程序员的关键步骤。通过实践和理解...

    java socket多线程聊天

    Java Socket多线程聊天程序是一种实现网络通信的基本方式,它基于TCP/IP协议,允许两台计算机之间进行双向数据传输。在这个简单的两人对话程序中,我们主要涉及到以下知识点: 1. **Socket**: Java中的Socket类是...

    java,socket多线程一对一聊天

    在本项目"java,socket多线程一对一聊天"中,我们探讨的是如何使用Java的Socket库来实现一个简单的、一对一的聊天应用。由于描述中提到“暂不支持并发”,我们可以理解这个系统可能只处理单个连接,而不是同时处理多...

    Java Socket 多线程通信

    Java Socket 多线程通信是网络编程中的一个重要概念,它涉及到Java的基础网络API以及多线程技术。在Java中,Socket是实现客户端-服务器通信的基础,而多线程则允许程序同时处理多个任务,这对于构建能够同时服务多个...

    Java多线程端口快速扫描

    Java多线程端口扫描是网络管理与安全领域中常用的一种技术,主要用于检测网络设备上哪些端口处于开放状态,从而分析网络的安全性或者优化网络配置。本程序通过利用Java的多线程特性,提高了扫描速度,使得在短时间内...

    java 多线程 socket聊天程序

    总之,Java多线程Socket聊天程序是学习网络编程和并发处理的好例子。它展示了如何使用Java的Socket API建立网络连接,以及如何通过多线程技术处理并发的客户端请求。通过理解和实践这样的项目,开发者可以深入理解...

    Java Socket 多线程实现文件传输

    Java Socket 多线程实现文件传输是一个常见的网络编程...通过以上介绍,你应该对Java Socket多线程实现文件传输有了基本的理解。实际开发中,还需要根据具体需求进行调整和优化,例如添加进度显示、文件校验等功能。

    SOCKET+多线程例子

    在实际开发中,使用Python、Java、C++等编程语言都可以实现Socket和多线程的结合。例如,Python的socket模块提供了创建和操作Socket的函数,而threading模块则支持多线程编程。对于初学者来说,这个例子提供了一个很...

    Java Socket实战之二 多线程通信 .

    本篇主要探讨的是如何在Java中实现多线程通信,利用Socket技术构建高效的并发服务器。我们将结合"Java Socket实战之二 多线程通信"这篇博文进行深入解析。 首先,了解Socket的基本概念。Socket在计算机网络中扮演着...

Global site tag (gtag.js) - Google Analytics