题:
做一个简单的网络控制软件,分为Server端和Client端,Server段填入一个有效的端口然后监听,Client端填入Server端的地址和端口号然后连接,连接以后双方可通信。
要求: (server绑定端口大于9000,用单独的Server类和单独的Client类封装SocketServer和Socket )
当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();
}
}