打开APP
未登录
开通VIP,畅享免费电子书等14项超值服
开通VIP
首页
好书
留言交流
下载APP
联系客服
Java 客户端服务器程序 学习笔记
醉三郎
>《Java》
2014.03.19
关注
Java 客户端服务器程序 学习笔记
博客分类:
Java SE--basic
Java
Socket
C#
C++
C
Java代码
//Server.java
package
com.mulThread;
import
java.awt.*;
import
java.awt.event.*;
import
javax.swing.*;
import
java.net.*;
import
java.io.*;
import
java.util.*;
/**
*
* @E-mail:youngmaster.fly@gmail.com
*
* @author:young master
*
* @version 1.0
*
* @any questions,please reply to me for deeping improvements
*/
public
class
Server
extends
JFrame {
JPanel contentPane;
JMenuBar jMenuBar1 =
new
JMenuBar();
JMenu jMenuFile =
new
JMenu();
JMenuItem jMenuFileExit =
new
JMenuItem();
JMenu jMenuHelp =
new
JMenu();
JMenuItem jMenuHelpAbout =
new
JMenuItem();
JLabel statusBar =
new
JLabel();
BorderLayout borderLayout1 =
new
BorderLayout();
JPanel jPanel1 =
new
JPanel();
BorderLayout borderLayout2 =
new
BorderLayout();
JLabel jLabel1 =
new
JLabel();
static
java.awt.List jList1 =
new
java.awt.List(
13
);
JScrollPane scrollpane =
new
JScrollPane(jList1);
// 以下为网络相关变量
static
Vector clients =
new
Vector(
10
);
// 用vector向量数组存储连接客户变量
static
ServerSocket server =
null
;
// 建立服务器socket
static
int
active_connects =
0
;
// 用来存储目前连接的客户数
static
Socket socket =
null
;
// 用来存储一个套接字连接
// chatServer main method
public
static
void
main(String[] args) {
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch
(Exception e) {
e.printStackTrace();
}
Server chatServer1 =
new
Server();
// 实例化一个chatServer类
chatServer1.show();
System.out.println(
"Server starting ..."
);
try
{
server =
new
ServerSocket(
2525
);
// 使用端口2525初始化服务器套接字
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
while
(
true
) {
if
(clients.size() <
5
)
// 当客户数小于5个时开始连接
{
try
{
socket = server.accept();
// 用来存储连接上的客户socket
if
(socket !=
null
) {
System.out.println(socket +
"连接"
);
// 在控制台打印客户连接信息
}
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
int
i =
0
;
do
{
Client c =
new
Client(socket);
// 定义并实例化一个Client线程类,一个就对应一个客户连接
clients.addElement(c);
// 加入clients数组中
if
(checkName(c))
// 调用checkName方法验证c的合法性
{
int
connum = ++chatServer1.active_connects;
// 定义connum来存储活动连接数
String constr =
"目前有"
+ connum +
"客户相连"
;
// 在状态栏里显示连接数
chatServer1.statusBar.setText(constr);
Client listdata = (Client) clients.elementAt(i);
// 将连接客户的socket信息存储进listdata数组
chatServer1.jList1.addItem(listdata.ip +
"连接"
, i);
// 将客户socket信息写入list框
c.start();
// 启动线程
notifyRoom();
// 用notifyRoom方法来监视聊天室连接变化
// 不断改变clients数组并刷新客户端信息
}
else
{
// 如果名字不合法
c.ps.println(
"TAKEN"
);
disconnect(c);
}
i++;
break
;
}
while
(i < clients.size());
}
else
// 如果clients数组超过了5个
{
try
{
Thread.sleep(
200
);
}
catch
(InterruptedException e) {
}
}
}
// end of while
}
// end of main method
/** Construct the frame */
public
Server()
// chatServer类的构造器用来初始化一些UI信息
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
jbInit();
}
catch
(Exception e) {
e.printStackTrace();
}
}
/** Component initialization */
private
void
jbInit()
throws
Exception {
// setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Your
// Icon]")));
contentPane = (JPanel)
this
.getContentPane();
contentPane.setLayout(borderLayout1);
this
.setSize(
new
Dimension(
400
,
300
));
this
.setTitle(
"简易聊天服务器端"
);
statusBar.setText(
"目前的连接数为:"
);
jMenuFile.setText(
"File"
);
jMenuFileExit.setText(
"Exit"
);
jMenuFileExit.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
jMenuFileExit_actionPerformed(e);
}
});
jMenuHelp.setText(
"Help"
);
jMenuHelpAbout.setText(
"About"
);
jMenuHelpAbout.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
jMenuHelpAbout_actionPerformed(e);
}
});
jPanel1.setLayout(borderLayout2);
jLabel1.setText(
"服务器端连接客户"
);
jMenuFile.add(jMenuFileExit);
jMenuHelp.add(jMenuHelpAbout);
jMenuBar1.add(jMenuFile);
jMenuBar1.add(jMenuHelp);
this
.setJMenuBar(jMenuBar1);
contentPane.add(statusBar, BorderLayout.SOUTH);
contentPane.add(jPanel1, BorderLayout.CENTER);
jPanel1.add(jLabel1, BorderLayout.NORTH);
jPanel1.add(scrollpane, BorderLayout.CENTER);
}
// end of jbinit
/** File | Exit action performed */
public
void
jMenuFileExit_actionPerformed(ActionEvent e)
// 实现退出菜单方法
{
sendClients(
new
StringBuffer(
"QUIT"
));
// 向客户端发送断开连接信息
closeAll();
// 调用closeAll方法关闭所有连接
System.exit(
0
);
}
/** Help | About action performed */
public
void
jMenuHelpAbout_actionPerformed(ActionEvent e)
// 实现about对话框,意义不大,可以去掉
{
AboutChat dlg =
new
AboutChat(
this
);
Dimension dlgSize = dlg.getPreferredSize();
Dimension frmSize = getSize();
Point loc = getLocation();
dlg.setLocation((frmSize.width - dlgSize.width) /
2
+ loc.x,
(frmSize.height - dlgSize.height) /
2
+ loc.y);
dlg.setModal(
true
);
dlg.show();
}
/** Overridden so we can exit when window is closed */
protected
void
processWindowEvent(WindowEvent e)
// 实现关闭服务器程序要进行的操作
{
super
.processWindowEvent(e);
if
(e.getID() == WindowEvent.WINDOW_CLOSING) {
jMenuFileExit_actionPerformed(
null
);
}
}
/* 以下实现各种方法 */
public
static
void
notifyRoom()
// 用来监视连接信息,不断刷新clients数组并刷新客户端用户列表信息
{
StringBuffer people =
new
StringBuffer(
"PEOPLE"
);
for
(
int
i =
0
; i < clients.size(); i++) {
Client c = (Client) clients.elementAt(i);
people.append(
":"
+ c.name);
}
sendClients(people);
// 用sendClients方法向客户端发送信息
}
public
static
synchronized
void
sendClients(StringBuffer msg)
// 实现sendClients方法专用来向每个连接的客户端发送信息
{
for
(
int
i =
0
; i < clients.size(); i++) {
Client c = (Client) clients.elementAt(i);
c.send(msg);
}
}
public
static
void
closeAll()
// 实现关闭所有连接信息
{
while
(clients.size() >
0
)
// 遍历clients数组删除所有连接客户信息
{
Client c = (Client) clients.firstElement();
try
{
c.socket.close();
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
finally
{
clients.removeElement(c);
}
}
// end of while
}
// end of closeAll method
public
static
boolean
checkName(Client newclient)
// 实现检查连接客户的socket信息是否合法
{
for
(
int
i =
0
; i < clients.size(); i++) {
Client c = (Client) clients.elementAt(i);
if
((c != newclient) && c.equals(newclient.name))
return
false
;
}
return
(
true
);
}
// end of checkName method
public
static
synchronized
void
disconnect(Client c)
// 实现断开单个客户的方法
{
try
{
jList1.addItem(c.ip +
"断开连接"
);
// 在服务器端程序的list框中显示断开信息
Server.active_connects--;
// 将连接数减1
c.send(
new
StringBuffer(
"QUIT"
));
// 向客户发送断开连接信息
c.socket.close();
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
finally
{
clients.removeElement(c);
// 从clients数组中删除此客户的相关socket等信息
}
}
}
class
Client
extends
Thread
// 实现 Client线程类
{
Socket socket;
// 用来存储一个连接客户的socket信息
String name;
// 用来存储客户的连接姓名
String ip;
// 用来存储客户的ip信息
DataInputStream dis;
// 用来实现接受从客户端发来的数据流
PrintStream ps;
// 用来实现向客户端发送信息的打印流
public
void
send(StringBuffer msg)
// 实现想客户端发送信息的方法
{
ps.println(msg);
// 用打印流发送信息
ps.flush();
}
public
Client(Socket s)
// Client线程类的构造器
{
socket = s;
try
{
dis =
new
DataInputStream(s.getInputStream());
// 存储特定客户socket的输入流接受s这个客户发送到服务器端的信息
ps =
new
PrintStream(s.getOutputStream());
// 存储特定客户socket的输出流发送服务器给s这个客户的信息
String info = dis.readLine();
// 读取接受来的信息
StringTokenizer stinfo =
new
StringTokenizer(info,
":"
);
// 用StringTokenizer类来读取用":"分段字符
String head = stinfo.nextToken();
// head用来存储类似于关键字的头信息
if
(stinfo.hasMoreTokens())
name = stinfo.nextToken();
// 关键字后的第二段数据是客户名信息
if
(stinfo.hasMoreTokens())
ip = stinfo.nextToken();
// 关键字后的第三段数据是客户ip信息
System.out.println(head);
// 在控制台打印头信息
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
}
// end of Client constrator
public
void
run()
// 线程运行方法
{
while
(
true
) {
String line =
null
;
try
{
line = dis.readLine();
// 读取客户端发来的数据流
}
catch
(IOException e) {
System.out.println(
"Error"
+ e);
Server.disconnect(
this
);
Server.notifyRoom();
return
;
}
if
(line ==
null
)
// 客户已离开
{
Server.disconnect(
this
);
Server.notifyRoom();
return
;
}
StringTokenizer st =
new
StringTokenizer(line,
":"
);
String keyword = st.nextToken();
if
(keyword.equals(
"MSG"
))
// 如果关键字是MSG则是客户端发来的聊天信息
{
StringBuffer msg =
new
StringBuffer(
"MSG:"
);
// 在服务器端再重新建立一个字符缓冲
msg.append(name);
msg.append(st.nextToken(
"\0"
));
Server.sendClients(msg);
// 再将某个客户发来的聊天信息发送到每个连接客户的聊天栏中
}
else
if
(keyword.equals(
"QUIT"
))
// 如果关键字是QUIT则是客户端发来断开连接的信息
{
Server.disconnect(
this
);
// 服务器断开与这个客户的连接
Server.notifyRoom();
// 继续监听聊天室并刷新其他客户的聊天人名list
this
.stop();
}
}
}
}
// end of class Client
//ClientChat.java
package
com.mulThread;
import
java.awt.*;
import
java.awt.event.*;
import
java.applet.*;
import
java.net.*;
import
java.io.*;
import
java.util.*;
/**
*
* @E-mail:youngmaster.fly@gmail.com
*
* @author:young master
*
* @version 1.0
*
* @any questions,please reply to me for deeping improvements
*/
public
class
ClientChat
extends
Applet {
/* 以下用于定义UI变量 */
Panel panel1 =
new
Panel();
// 用于放置输入姓名和连接两个按钮
BorderLayout borderLayout1 =
new
BorderLayout();
Panel panel2 =
new
Panel();
// 用于放置聊天信息显示和聊天人员列表
Panel panel3 =
new
Panel();
// 用于放置发送信息区域
FlowLayout flowLayout1 =
new
FlowLayout();
FlowLayout flowLayout2 =
new
FlowLayout();
Label label1 =
new
Label();
TextField name_txt =
new
TextField(
15
);
Button button1 =
new
Button();
Button button2 =
new
Button();
TextArea chat_txt =
new
TextArea(
15
,
30
);
Label label2 =
new
Label();
Button button3 =
new
Button();
TextField msg_txt =
new
TextField(
20
);
java.awt.List list1 =
new
java.awt.List(
13
);
/* 以下定义数据流和网络变量 */
Socket soc =
null
;
// 定义连接套接字
PrintStream ps =
null
;
// 定义打印流
Listen listen =
null
;
// 定义一个客户端线程
public
void
init()
// 初始化图形界面
{
resize(
475
,
350
);
this
.setLayout(borderLayout1);
panel2.setLayout(flowLayout1);
panel3.setLayout(flowLayout2);
label1.setText(
"用户名:"
);
button1.setLabel(
"连接"
);
button2.setLabel(
"断开连接"
);
chat_txt.setEditable(
false
);
panel2.setBackground(Color.cyan);
panel1.setBackground(Color.cyan);
label2.setText(
"聊天信息:"
);
button3.setLabel(
"发送"
);
msg_txt.setText(
"请输入聊天信息"
);
panel3.setBackground(Color.cyan);
this
.add(panel1, BorderLayout.NORTH);
panel1.add(label1,
null
);
panel1.add(name_txt,
null
);
panel1.add(button1,
null
);
panel1.add(button2,
null
);
this
.add(panel2, BorderLayout.CENTER);
panel2.add(chat_txt,
null
);
panel2.add(list1,
null
);
this
.add(panel3, BorderLayout.SOUTH);
panel3.add(label2,
null
);
panel3.add(msg_txt,
null
);
panel3.add(button3,
null
);
}
public
boolean
action(Event evt, Object obj)
// 事件触发代码
{
if
(evt.target
instanceof
Button) {
String label = (String) obj;
if
(label.equals(
"连接"
))
// 如果点击连接后
{
if
(soc ==
null
) {
try
{
soc =
new
Socket(InetAddress.getLocalHost(),
2525
);
// 使用端口2525实例化一个本地套接字
System.out.println(soc);
// 在控制台打印实例化的结果
ps =
new
PrintStream(soc.getOutputStream());
// 将ps指向soc的输出流
StringBuffer info =
new
StringBuffer(
"INFO: "
);
// 定义一个字符缓冲存储发送信息
// 其中INFO为关键字让服务器识别为连接信息
// 并将name和ip用":"分开,在服务器端将用一个
// StringTokenizer类来读取数据
String userinfo = name_txt.getText() +
":"
+ InetAddress.getLocalHost().toString();
ps.println(info.append(userinfo));
ps.flush();
listen =
new
Listen(
this
, name_txt.getText(), soc);
// 将客户端线程实例化
listen.start();
// 启动线程
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
disconnect();
}
}
// end of if
}
// end of if
else
if
(label.equals(
"断开连接"
))
// 如果点击断开连接按钮则运行disconnect()
{
disconnect();
}
else
if
(label.equals(
"发送"
))
// 如果点击发送按钮
{
if
(soc !=
null
) {
StringBuffer msg =
new
StringBuffer(
"MSG: "
);
// 定义并实例化一个字符缓冲存储发送的聊天信息
// 其中MSG为关键词
try
{
String msgtxt =
new
String(msg_txt.getText());
}
catch
(Exception e) {
}
ps.println(msg.append(msg_txt.getText()));
// 用打印流发送聊天信息
ps.flush();
}
}
}
return
true
;
}
// end of method action
public
void
disconnect()
// 客户端点击断开连接要运行的方法
{
if
(soc !=
null
) {
try
{
listen.suspend();
ps.println(
"QUIT"
);
// 用打印流发送QUIT信息通知服务器断开此次通信
ps.flush();
soc.close();
// 关闭套接字
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
finally
{
}
}
// end of if
}
class
Listen
extends
Thread
// 客户端线程类用来监听服务器传来的信息
{
String name =
null
;
// 用来存储客户端连接后的name信息
DataInputStream dis =
null
;
// 用来实现客户端接受服务器数据的输入流
PrintStream ps =
null
;
// 用来实现从客户端发送数据到服务器的打印流
Socket socket =
null
;
// 用来存储客户端的socket信息
ClientChat parent =
null
;
// 用来存储当前运行的chatApplet实例
public
Listen(ClientChat p, String n, Socket s)
// Listen类的构造器
{
// 接受参数
parent = p;
name = n;
socket = s;
try
{
// 实例化两个数据流
dis =
new
DataInputStream(s.getInputStream());
ps =
new
PrintStream(s.getOutputStream());
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
parent.disconnect();
}
}
// end of Listen constractor
public
void
run()
// 线程运行方法
{
String msg =
null
;
while
(
true
) {
try
{
msg = dis.readLine();
}
// 读取从服务器传来的信息
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
parent.disconnect();
}
if
(msg ==
null
)
// 如果从服务器传来的信息为空则断开此次连接
{
parent.listen =
null
;
parent.soc =
null
;
parent.list1.clear();
return
;
}
StringTokenizer st =
new
StringTokenizer(msg,
":"
);
// 用StringTokenizer类来实现读取分段字符
String keyword = st.nextToken();
// 读取信息头即关键字用来识别是何种信息
if
(keyword.equals(
"PEOPLE"
))
// 如果是PEOPLE则是服务器发来的客户连接信息
// 主要用来刷新客户端的用户列表
{
parent.list1.clear();
while
(st.hasMoreTokens())
// 遍历st取得目前所连接的客户
{
String str = st.nextToken();
parent.list1.addItem(str);
}
}
else
if
(keyword.equals(
"MSG"
))
// 如果关键字是MSG则是服务器传来的聊天信息
// 主要用来刷新客户端聊天信息区将每个客户的聊天内容显示出来
{
String usr = st.nextToken();
parent.chat_txt.appendText(usr);
parent.chat_txt.appendText(st.nextToken(
"\0"
));
parent.chat_txt.appendText(
"\n\n"
);
}
else
if
(keyword.equals(
"QUIT"
))
// 如果关键字是QUIT则是服务器关闭的信息
// 用来切断此次连接
{
System.out.println(
"Quit"
);
try
{
parent.listen.stop();
parent.listen =
null
;
parent.soc.close();
parent.soc =
null
;
}
catch
(IOException e) {
System.out.println(
"Error:"
+ e);
}
parent.list1.clear();
return
;
}
}
}
// end of run method
}
// end of Listen inner class
}
// end of chatApplet class
//AboutChat.java
package
com.mulThread;
import
java.awt.*;
import
java.awt.event.*;
import
javax.swing.*;
import
javax.swing.border.*;
/**
*
* @E-mail:youngmaster.fly@gmail.com
*
* @author:young master
*
* @version 1.0
*
* @any questions,please reply to me for deeping improvements
*/
public
class
AboutChat
extends
JDialog
implements
ActionListener {
JPanel panel1 =
new
JPanel();
JPanel panel2 =
new
JPanel();
JPanel insetsPanel1 =
new
JPanel();
JPanel insetsPanel2 =
new
JPanel();
JPanel insetsPanel3 =
new
JPanel();
JButton button1 =
new
JButton();
JLabel imageLabel =
new
JLabel();
JLabel label1 =
new
JLabel();
JLabel label2 =
new
JLabel();
JLabel label3 =
new
JLabel();
JLabel label4 =
new
JLabel();
BorderLayout borderLayout1 =
new
BorderLayout();
BorderLayout borderLayout2 =
new
BorderLayout();
FlowLayout flowLayout1 =
new
FlowLayout();
GridLayout gridLayout1 =
new
GridLayout();
String product =
"product:少爷精简版--聊天服务器端"
;
String author =
"author:young master "
+
"any questions,please reply to me for deeping improvements"
;
String email =
"@E-mail:youngmaster.fly@gmail.com"
;
String comments =
"本聊天室服务器端实现了多线程客户连接和显示连接信息"
;
public
AboutChat(Frame parent) {
super
(parent);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
jbInit();
}
catch
(Exception e) {
e.printStackTrace();
}
pack();
}
private
void
jbInit()
throws
Exception {
//imageLabel.setIcon(new ImageIcon(Frame1_AboutBox.class.getResource("[Your Image]")));
this
.setTitle(
"少爷精简版--聊天服务器端"
);
setResizable(
false
);
panel1.setLayout(borderLayout1);
panel2.setLayout(borderLayout2);
insetsPanel1.setLayout(flowLayout1);
insetsPanel2.setLayout(flowLayout1);
insetsPanel2.setBorder(BorderFactory.createEmptyBorder(
10
,
10
,
10
,
10
));
gridLayout1.setRows(
4
);
gridLayout1.setColumns(
1
);
label1.setText(product);
label2.setText(author);
label3.setText(email);
label4.setText(comments);
insetsPanel3.setLayout(gridLayout1);
insetsPanel3.setBorder(BorderFactory.createEmptyBorder(
10
,
60
,
10
,
10
));
button1.setText(
"Ok"
);
button1.addActionListener(
this
);
insetsPanel2.add(imageLabel,
null
);
panel2.add(insetsPanel2, BorderLayout.WEST);
this
.getContentPane().add(panel1,
null
);
insetsPanel3.add(label1,
null
);
insetsPanel3.add(label2,
null
);
insetsPanel3.add(label3,
null
);
insetsPanel3.add(label4,
null
);
panel2.add(insetsPanel3, BorderLayout.CENTER);
insetsPanel1.add(button1,
null
);
panel1.add(insetsPanel1, BorderLayout.SOUTH);
panel1.add(panel2, BorderLayout.NORTH);
}
/**Overridden so we can exit when window is closed*/
protected
void
processWindowEvent(WindowEvent e) {
if
(e.getID() == WindowEvent.WINDOW_CLOSING) {
cancel();
}
super
.processWindowEvent(e);
}
/**Close the dialog*/
void
cancel() {
dispose();
}
/**Close the dialog on a button event*/
public
void
actionPerformed(ActionEvent e) {
if
(e.getSource() == button1) {
cancel();
}
}
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报
。
打开APP,阅读全文并永久保存
查看更多类似文章
猜你喜欢
类似文章
【热】
打开小程序,算一算2024你的财运
告诉大家一个吃透“鸡兔同笼”的秘密:那就是下图这4大版块共计27
电脑最牛的两大终极操作,学会了,让你的电脑一直保持流畅!#程序员
摄影:南京夫子庙and秦淮河畔(16)
南京的一座标志性建筑~南京眼
这样的练字讲解,谁会不爱,谁会练不好?
地球上的石油,究竟是怎么形成的?看完这个,你就懂了
更多类似文章 >>
生活服务
热点新闻
留言交流
回顶部
联系我们
分享
收藏
点击这里,查看已保存的文章
导长图
关注
一键复制
下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!
联系客服
微信登录中...
请勿关闭此页面
先别划走!
送你5元优惠券,购买VIP限时立减!
5
元
优惠券
优惠券还有
10:00
过期
马上使用
×