在看到本文之前馋劈,如果讀者沒看過筆者的前文Java實現(xiàn)Socket網(wǎng)絡(luò)編程(一) ,請先翻閱偶洋。在閱讀本文前熟吏,讀者應(yīng)先具備Java的Swing編程的基礎(chǔ)知識。
首先玄窝,我們編寫服務(wù)器的界面:
JFrame mainFrame = new ServerMain();
mainFrame.setTitle("server");
mainFrame.setSize(545, 395);
// 設(shè)置顯示位置為正中間
mainFrame.setLocationRelativeTo(null);
// 設(shè)置布局文件為空牵寺,以讓組件可使用絕對布局setBounds
mainFrame.setLayout(null);
// 大小不可變
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
// 設(shè)置IPAddress標(biāo)簽
JLabel jlIP = new JLabel("IPAddress:");
jlIP.setBounds(10, 15, 70, 25);
add(jlIP);
// 設(shè)置IPAddress顯示文本
JTextField jtfIP = new JTextField();
jtfIP.setText("127.0.0.1");
jtfIP.setEditable(false);
jtfIP.setBounds(80, 15, 185, 25);
jtfIP.setText(Common.IP);
add(jtfIP);
// 設(shè)置Port標(biāo)簽
JLabel jlPort = new JLabel("Port:");
jlPort.setBounds(10, 50, 70, 25);
add(jlPort);
// 設(shè)置Port顯示文本
JTextField jtfPort = new JTextField();
jtfPort.setText("10055");
jtfPort.setEditable(false);
jtfPort.setBounds(80, 50, 185, 25);
jtfPort.setText(Common.PORT + "");
add(jtfPort);
// 設(shè)置Client標(biāo)簽
JLabel jlClient = new JLabel("Choose Client:");
jlClient.setBounds(15, 90, 100, 25);
add(jlClient);
// 創(chuàng)建Client列表
model = new DefaultListModel<>();
clientList = new JList<String>(model);
clientList.setBorder(BorderFactory.createLineBorder(Color.black));
// 設(shè)置多選模式
clientList
.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
clientList.setFocusable(true);
// 添加滾動
jpclientList = new JScrollPane(clientList);
jpclientList.setBounds(10, 115, 255, 65);
add(jpclientList);
// 設(shè)置Send Message標(biāo)簽
JLabel jlSendMessage = new JLabel("Send Message:");
jlSendMessage.setBounds(15, 185, 100, 25);
add(jlSendMessage);
// 設(shè)置Send Message文本
jtaSendMessage = new JTextArea();
// 激活自動換行功能
jtaSendMessage.setLineWrap(true);
// 激活斷行不斷字功能
jtaSendMessage.setWrapStyleWord(true);
// 設(shè)置黑色邊框
jtaSendMessage.setBorder(BorderFactory.createLineBorder(Color.black));
// 添加滾動條
JScrollPane jpSendMessage = new JScrollPane(jtaSendMessage);
jpSendMessage.setBounds(10, 210, 255, 100);
add(jpSendMessage);
// 設(shè)置Connect標(biāo)簽
jlConnect = new JLabel("0 Connect success.");
jlConnect.setBounds(15, 320, 130, 25);
add(jlConnect);
// 設(shè)置Send Message按鈕
JButton jbSendMessage = new JButton("SendMessage");
jbSendMessage.setBounds(145, 320, 120, 25);
add(jbSendMessage);
// 設(shè)置Received Message標(biāo)簽
JLabel jlReceivedMessage = new JLabel("Received Message:");
jlReceivedMessage.setBounds(295, 15, 130, 25);
add(jlReceivedMessage);
// 設(shè)置Received Message文本
jtaReceivedMessage = new JTextArea();
// 激活自動換行功能
jtaReceivedMessage.setLineWrap(true);
// 激活斷行不斷字功能
jtaReceivedMessage.setWrapStyleWord(true);
// 設(shè)置不可編輯
jtaReceivedMessage.setEditable(false);
// 設(shè)置黑色邊框
jtaReceivedMessage.setBorder(BorderFactory
.createLineBorder(Color.black));
// 添加滾動條
JScrollPane jpReceivedMessage = new JScrollPane(jtaReceivedMessage);
jpReceivedMessage.setBounds(285, 40, 230, 305);
add(jpReceivedMessage);
然后,我們編寫客戶端界面:因客戶端界面和服務(wù)器界面大體相似恩脂,筆者在此處就不粘貼代碼了帽氓。值得注意的是,客戶端和服務(wù)器應(yīng)是兩個不同的Java Project俩块。
根據(jù)設(shè)計思路黎休,我們?yōu)榉?wù)器創(chuàng)建一個ServerSocket,監(jiān)聽4703端口玉凯,并啟動一個主監(jiān)聽線程势腮,監(jiān)測是否有客戶端連接。
try {
// 創(chuàng)建監(jiān)聽4703端口的ServerSocket
serverSocket = new ServerSocket(Common.PORT);
// 啟動一個監(jiān)聽線程
listenThread = new Thread(new ListenThread());
listenThread.start();
} catch (Exception e1) {
e1.printStackTrace();
}
實際上漫仆,可采用大于1024的任意端口捎拯,筆者選用4703端口,是因為此端口很少被占用盲厌,能在不同的機(jī)器上運行時不會產(chǎn)生端口沖突署照。小于1024的端口都是綁定給特定的服務(wù),所以一般除了那些專門提供某服務(wù)的軟件可以用吗浩,別的軟件一般不用建芙。
下面,我們來實現(xiàn)服務(wù)器主監(jiān)聽線程ListenThread:
// 響應(yīng)一個請求
Socket clientSocket = ServerMain.serverSocket.accept();
// 創(chuàng)建一個子線程和客戶端保持連接
new Thread(new ServerReceiverThread(clientSocket)).start();
// 添加到Socket請求隊列
HashMap<Socket, Boolean> map = new HashMap<Socket, Boolean>();
map.put(clientSocket, false);
clientSockets.add(map);
通過ServerSocket的accept()方法拓萌,去響應(yīng)一個連接請求岁钓,并創(chuàng)建一個與客戶端交互的Socket對象,把Socket對象添加到請求隊列微王,為后期發(fā)送消息做準(zhǔn)備屡限。同時創(chuàng)建一個子線程,用于接收客戶端消息炕倘。