Java的Socket通信小程序(双向通信版本)

学习说明

Socket通信小程序
	实现客户端与服务器端双向通信

要点:
	网络编程一些常用函数的使用
	多线程的基本使用
	界面的绘制


学习资料为:《Java语言程序设计》梁勇

运行效果

服务器端
在这里插入图片描述

客户端
在这里插入图片描述

源码如下

存在的问题:通信会出现客户端向服务器端发送失灵,找了很久,不知道是啥情况

服务器端代码

public class Server extends JFrame {
	private static final long serialVersionUID = 1L;
	
	private int port = 8000;
	private boolean isServerStarted = false;
	
	private JPanel panelConfig = new JPanel(new BorderLayout(5, 5));
	private JLabel jlblPort = new JLabel("Port:");
	private JTextField jtfPort = new JTextField();
	private JButton jbtnStart = new JButton("Start");
	
	private JTextArea jtaMsg = new JTextArea();
	private JScrollPane scrollPane = new JScrollPane(jtaMsg);
	
	private JPanel panelSend = new JPanel(new FlowLayout());
	private JLabel jlblSend = new JLabel("Say:");
	private JTextField jtfSend = new JTextField(33);
	private JComboBox<String> jcboClientList = new JComboBox<String>();
	private JButton jbtnSend = new JButton("Say");
	
	// 最多10个客户端
	private DataInputStream[] fromClient = new DataInputStream[10];
	private DataOutputStream[] toClient = new DataOutputStream[10];
	
	public static int clientNo = 1;
	private static int selectClientNo = 0;
	
	public Server() {
		panelConfig.add(jlblPort, BorderLayout.WEST);
		panelConfig.add(jtfPort, BorderLayout.CENTER);
		panelConfig.add(jbtnStart, BorderLayout.EAST);
		panelConfig.setBorder(new TitledBorder("服务器设置"));
		
		jtaMsg.setBorder(new LineBorder(Color.GRAY, 1));
		
		panelSend.add(jlblSend);
		panelSend.add(jtfSend);
		panelSend.add(jcboClientList);
		panelSend.add(jbtnSend);
		
		JPanel panelAll = new JPanel(new BorderLayout(5, 5));
		panelAll.setBorder(new EmptyBorder(10, 10, 10, 10));
		panelAll.add(panelConfig, BorderLayout.NORTH);
		panelAll.add(scrollPane, BorderLayout.CENTER);
		panelAll.add(panelSend, BorderLayout.SOUTH);
		
		add(panelAll);
		
		setTitle("服务器");
		setSize(600, 400);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
		jbtnStart.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (!isServerStarted) {
					isServerStarted = true;
					
					Thread threadService = new Thread(new Service());
					Thread threadReceive = new Thread(new ReceiveMsg());
					threadService.start();
					threadReceive.start();
				}
			}
		});
		
		jbtnSend.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				sendMsgToClient();
			}
		});
		
		jcboClientList.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				selectClientNo = jcboClientList.getSelectedIndex();
			}
		});
	}
	
	public void sendMsgToClient() {
		if(toClient != null) {
			String sendMsg = jtfSend.getText().trim();
			if(!sendMsg.equalsIgnoreCase("")) {
				try {
					toClient[selectClientNo].writeUTF("Server:" + sendMsg);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private class Service implements Runnable {
		@Override
		public void run() {
			ServerSocket serverSocket = null;
			try {
				serverSocket = new ServerSocket(port);
				jtaMsg.append("Server started at " + new Date() + " at " + port + "\n");
				
				while (true && clientNo <= 10) {
					Socket socket = serverSocket.accept();
					
					jtaMsg.append("Starting thread for client " + clientNo + " at" + new Date() + "\n");
					
					InetAddress inetAddress = socket.getInetAddress();
					jtaMsg.append("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
					jtaMsg.append("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
					
					jcboClientList.addItem("Client " + clientNo);
					
					fromClient[clientNo - 1] = new DataInputStream(socket.getInputStream());
					toClient[clientNo - 1] = new DataOutputStream(socket.getOutputStream());
					
					clientNo++;
				}
			} catch (IOException e) {
				// 这里为了好看就不打印了
			}
		}
	}
	
	private class ReceiveMsg implements Runnable {
		@Override
		public void run() {
			while (true) {
				try {
					for (int i = 0; i < clientNo; i++) {
						if(fromClient[i] != null)
							jtaMsg.append(fromClient[i].readUTF() + "\n");
					}
				} catch (IOException e) {
					// 这里为了好看就不打印了
				}
			}
		}
	}
}

客户端代码

public class Client extends JFrame {
	private static final long serialVersionUID = 1L;
	
	private String host = "127.0.0.1";
	private int port = 8000;
	private boolean isServerConnected = false;
	
	private JPanel panelConfig = new JPanel(new FlowLayout());
	private JLabel jlblIP = new JLabel("Server IP:");
	private JTextField jtfIP = new JTextField(14);
	private JLabel jlblPort = new JLabel("Server Port:");
	private JTextField jtfPort = new JTextField(14);
	private JButton jbtnConnect = new JButton("Connect");
	
	private JTextArea jtaMsg = new JTextArea();
	private JScrollPane scrollPane = new JScrollPane(jtaMsg);
	
	private JPanel panelSend = new JPanel(new BorderLayout(5, 5));
	private JLabel jlblSend = new JLabel("Say:");
	private JTextField jtfSend = new JTextField();
	private JButton jbtnSend = new JButton("Say");
	
	private DataInputStream fromServer = null;
	private DataOutputStream toServer = null;
	
	private int clientNo = 0;
	private String sendMsg;
	
	public Client() {
		panelConfig.add(jlblIP);
		panelConfig.add(jtfIP);
		panelConfig.add(jlblPort);
		panelConfig.add(jtfPort);
		panelConfig.add(jbtnConnect);
		panelConfig.setBorder(new TitledBorder("客户机设置"));
		
		jtaMsg.setBorder(new LineBorder(Color.GRAY, 1));
		jtaMsg.append("Wait to connect server\n");
		
		panelSend.add(jlblSend, BorderLayout.WEST);
		panelSend.add(jtfSend, BorderLayout.CENTER);
		panelSend.add(jbtnSend, BorderLayout.EAST);
		
		JPanel panelAll = new JPanel(new BorderLayout(5, 5));
		panelAll.setBorder(new EmptyBorder(10, 10, 10, 10));
		panelAll.add(panelConfig, BorderLayout.NORTH);
		panelAll.add(scrollPane, BorderLayout.CENTER);
		panelAll.add(panelSend, BorderLayout.SOUTH);
		
		add(panelAll);
		
		setTitle("客户端");
		setSize(600, 400);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setVisible(true);
		
		jbtnConnect.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String hostName = jtfIP.getText().trim();
				String portName = jtfPort.getText().trim();
				if(!(hostName.equalsIgnoreCase("") && portName .equalsIgnoreCase(""))) {
					host = hostName;
					port = Integer.parseInt(portName);
				}
				
				if (!isServerConnected) {
					isServerConnected = true;
					connect();
				}
			}
		});
		
		jbtnSend.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				sendMsgToServer();
			}
		});
	}
	
	public void sendMsgToServer() {
		if(toServer != null) {
			sendMsg = jtfSend.getText().trim();
			if(!sendMsg.equalsIgnoreCase("")) {
				try {
					toServer.writeUTF("Client:" + clientNo + ":" + sendMsg);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private void connect() {
		Socket socket = null;
		while (socket == null) {
			try {
				socket = new Socket(host, port);
				fromServer = new DataInputStream(socket.getInputStream());
				toServer = new DataOutputStream(socket.getOutputStream());
				
				jtaMsg.append("Connect to server " + host + port + "\n");
				
				String firstMsg = "Client connected!";
				toServer.writeUTF(firstMsg);
				
				clientNo = Server.clientNo;
				
				Thread thread = new Thread(new ReceiveMsg());
				thread.start();
				
			} catch (IOException e) {
				if(socket != null)
					jtaMsg.append(e.getMessage());
			}
			if(socket != null) {
				jtaMsg.append("connect successfully!\n");
			}
		}
	}
	
	private class ReceiveMsg implements Runnable {
		@Override
		public void run() {
			while (true) {
				try {
					jtaMsg.append(fromServer.readUTF() + "\n");
				} catch (IOException e) {
					// 这里为了好看就不打印了
				}
			}
		}
	}
}

控制界面

public class ControlWindow extends JFrame {
	private static final long serialVersionUID = 1L;
	
	private JButton jbtnShowMsg = new JButton("Show Rules");
	private JButton jbtnStartServer = new JButton("Start Server");
	private JButton jbtnStartClient = new JButton("Start Client");
	private JButton jbtnExit = new JButton("Exit");
	
	private boolean isServerStart = false;
	
	public static void main(String[] args) {
		JFrame frame = new ControlWindow();
		
		frame.setTitle("Socket Chat");
		frame.setSize(700, 400);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
	public ControlWindow() {
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());

		JTextArea jtaMsg = new JTextArea();
		
		panel.add(jbtnShowMsg, BorderLayout.WEST);
		panel.add(jbtnStartServer, BorderLayout.NORTH);
		panel.add(jbtnStartClient, BorderLayout.EAST);
		panel.add(jtaMsg, BorderLayout.CENTER);
		panel.add(jbtnExit, BorderLayout.SOUTH);
		
		setLayout(new BorderLayout());
		add(panel, BorderLayout.CENTER);
		
		jbtnStartClient.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				new Client();
			}
		});
		
		jbtnStartServer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(!isServerStart) {
					new Server();
					isServerStart = true;
				}
			}
		});
		
		jbtnExit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int select = JOptionPane.showConfirmDialog(null, "Confirm to exit?");
				if(select == 0)
					System.exit(0);
			}
		});
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您讲解基于Socket类的Java网络编程实现聊天小程序。 首先,我们需要了解Socket类是Java中用于实现网络通信的类,它提供了客户端和服务器端的通信功能。在聊天小程序中,我们需要使用Socket类来建立客户端与服务器端之间的连接。 在客户端中,我们需要创建一个Socket对象,并指定服务器端的IP地址和端口号,通过Socket对象的输入输出流进行数据的传输。具体代码如下: ```java Socket clientSocket = new Socket("服务器IP地址", 服务器端口号); OutputStream outToServer = clientSocket.getOutputStream(); DataOutputStream out = new DataOutputStream(outToServer); out.writeUTF("Hello from " + clientSocket.getLocalSocketAddress()); InputStream inFromServer = clientSocket.getInputStream(); DataInputStream in = new DataInputStream(inFromServer); System.out.println("服务器响应:" + in.readUTF()); clientSocket.close(); ``` 在服务器端中,我们需要创建一个ServerSocket对象,并指定监听的端口号,通过ServerSocket对象的accept()方法监听客户端的连接请求,并通过输入输出流进行数据的传输。具体代码如下: ```java ServerSocket serverSocket = new ServerSocket(服务器端口号); System.out.println("等待客户端连接..."); Socket server = serverSocket.accept(); System.out.println("客户端连接成功:" + server.getRemoteSocketAddress()); DataInputStream in = new DataInputStream(server.getInputStream()); System.out.println(in.readUTF()); DataOutputStream out = new DataOutputStream(server.getOutputStream()); out.writeUTF("谢谢连接:" + server.getLocalSocketAddress() + "\nGoodbye!"); server.close(); ``` 以上代码是一个简单的示例,实现了客户端与服务器端之间的数据传输。在实际的聊天小程序中,我们需要不断地接收客户端发送的消息,并广播给所有连接的客户端,同时也需要处理客户端的退出等情况。 希望以上内容能够对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值