package com.ui.server;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ServerBootFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
JPanel jp = new JPanel(new BorderLayout());
JPanel jp1 = new JPanel(new FlowLayout());
JScrollPane jsp1 = new JScrollPane();
JButton jbStart = new JButton("启动");
JButton jbEnd = new JButton("关闭");
JTextArea jtaState = new JTextArea(10, 25);
Font font = new Font("Serif", Font.BOLD, 18);
Color fore = Color.YELLOW;
Color back = new Color(81, 217, 251);
public ServerBootFrame(String title) {
super(title);
this.getContentPane().add(jp);
jp.add(jsp1, "Center");
jsp1.getViewport().add(jtaState);
jp.add(jp1, "South");
jp1.add(jbStart);
jp1.add(jbEnd);
jtaState.setFont(font);
jtaState.setForeground(fore);
jtaState.setBackground(back);
jp1.setBackground(back);
this.setResizable(false);
this.setLocation(250, 250);
}
public void showFrame() {
this.pack();
this.setVisible(true);
}
public void bootingServer(final BootEndInterface bt) {
this.jbStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
bt.boot();
}
});
}
public void endingServer(final BootEndInterface ed) {
this.jbEnd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ed.end();
}
});
}
public void closeWindow(final BootEndInterface ed) {
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e1) {
ed.end();
}
});
}
public void appendStringTojtaState(String str) {
jtaState.append(str);
}
}
package com.ui.client;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.sql.*;
public class LoginFrame extends JFrame
{
JLabel jUserName=new JLabel("用户姓名:");
JLabel jUserPsd=new JLabel("用户密码:");
JTextField txtUserName=new JTextField("",10);
JPasswordField txtUserPsd=new JPasswordField(10);
JButton okButton=new JButton("确定");
JButton regButton=new JButton("注册");
JPanel jp=new JPanel(new GridLayout(2,1));
JPanel jp1=new JPanel(new FlowLayout(FlowLayout.CENTER));
JPanel jp2=new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel jp3=new JPanel(new FlowLayout());
Font f=new Font("Serif",Font.BOLD,15);
public LoginFrame()
{
super("用户登陆界面");
this.setLocation(250,250);
this.getContentPane().add(jp,"Center");
this.getContentPane().add(jp3,"South");
jp.add(jp1);jp.add(jp2);
jp1.add(jUserName);jp1.add(txtUserName);
jp2.add(jUserPsd);jp2.add(txtUserPsd);
jp3.add(okButton);jp3.add(regButton);
txtUserName.setFont(f);
txtUserPsd.setFont(f);
txtUserPsd.setEchoChar('x');
txtUserName.setToolTipText("请输入用户名");
txtUserPsd.setToolTipText("请输入用户密码");
okButton.addActionListener(new SolveButtonEvent(1));
regButton.addActionListener(new SolveButtonEvent(2));
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void showWindow()
{
this.pack();
this.setVisible(true);
}
public void closeWindow()
{
this.dispose();
}
public String getUserName()
{
return this.txtUserName.getText().trim();
}
public String getUserPassword()
{
return new String(this.txtUserPsd.getPassword());
}
class SolveButtonEvent implements ActionListener
{
int select=0;
public SolveButtonEvent(int select)
{
this.select=select;
}
public void actionPerformed(ActionEvent e)
{
//int x=(int) LoginFrame.this.txtUserName.getLocationOnScreen().getX();
//int y=(int) LoginFrame.this.txtUserName.getLocationOnScreen().getY();
String userName=LoginFrame.this.getUserName();
String userPsd=LoginFrame.this.getUserPassword();
int nameLength=userName.length();
int psdLength=userPsd.length();
if(select==1)
{ if(nameLength>0 && psdLength>0 )
{
if(LoginFrame.this.query(userName,userPsd)==true)
{
LoginFrame.this.closeWindow();
//new Client();
}
else
{
MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","错误!","用户名或密码错误.\n登陆失败");
md.showDialog();
}
}
else
{
if(nameLength==0)
{
MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","提示","用户名不能为空");
md.showDialog();
}
else if(psdLength==0)
{
MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","提示","用户密码不能为空");
md.showDialog();
}
}
}
else if(select==2)
{
RegisterFrame rf=new RegisterFrame(LoginFrame.this);
rf.showWindow();
}
}
}
public boolean query(String userName,String userPsd)
{
Connection conn=null;
PreparedStatement psm=null;
ResultSet rs=null;
String sql="select * from user_manager where name=? and psd=?";
boolean result=false;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xdf","scott","tiger");
psm=conn.prepareStatement(sql);
psm.setString(1,userName);
psm.setString(2,userPsd);
rs=psm.executeQuery();
//rs结果集指向第一条记录的前一个位置
//如果第一条记录为空表示用户名或密码错误
if(rs.next()==true)
{
result=true;
this.closeWindow();
}
psm.close();
conn.close();
}
catch(ClassNotFoundException e1){ e1.printStackTrace(); }
catch(SQLException e2){ e2.printStackTrace(); }
catch(Exception e3){ e3.printStackTrace(); }
return result;
}
}
package com.nio.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import com.nio.user.ClientUser;
import com.nio.user.ClientUserManager;
import com.nio.user.UserData;
public class NIOClient {
private ClientUserManager cltManager = null;
//通道管理器
private Selector selector;
/**
* 获得一个Socket通道,并对该通道做一些初始化的工作
* @param ip 连接的服务器的ip
* @param port 连接的服务器的端口号
* @throws IOException
*/
public void initClient(String ip,int port) throws IOException {
cltManager = ClientUserManager.instance();
// 获得一个Socket通道
SocketChannel channel = SocketChannel.open();
// 设置通道为非阻塞
channel.configureBlocking(false);
// 获得一个通道管理器
this.selector = Selector.open();
// 客户端连接服务器,其实方法执行并没有实现连接,需要在listen()方法中调
//用channel.finishConnect();才能完成连接
channel.connect(new InetSocketAddress(ip,port));
//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT事件。
channel.register(selector, SelectionKey.OP_CONNECT);
}
/**
* 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理
* @throws IOException
* @throws InterruptedException
*/
@SuppressWarnings("unchecked")
public void listen() throws IOException, InterruptedException {
// 轮询访问selector
while (true) {
// 选择一组可以进行I/O操作的事件,放在selector中,客户端的该方法不会阻塞,
//这里和服务端的方法不一样,查看api注释可以知道,当至少一个通道被选中时,
//selector的wakeup方法被调用,方法返回,而对于客户端来说,通道一直是被选中的
selector.select();
// 获得selector中选中的项的迭代器
Iterator ite = this.selector.selectedKeys().iterator();
while (ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
// 连接事件发生
if (key.isConnectable()) {
SocketChannel channel = (SocketChannel) key
.channel();
System.out.println("channel client ?" + channel);
// 如果正在连接,则完成连接
if(channel.isConnectionPending()){
channel.finishConnect();
}
//设置成非阻塞
channel.configureBlocking(false);
//在这里可以给服务端发送信息哦
//channel.write(ByteBuffer.wrap(new String("向服务端发送了一条信息").getBytes()));
//在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。
channel.register(this.selector, SelectionKey.OP_READ);
//添加用户
UserData userData = new UserData();
userData.lineState = 1;
userData.channel = channel;
cltManager.addUser(userData);
//连接成功发送一个通知消息
UIClient.sendUserInfoMsg();
} else if (key.isReadable()) {
ClientUser cltUser = cltManager.getUser((SocketChannel)key.channel());
if (!cltUser.read()) {
key.channel().close();
}
}
//删除已选的key,以防重复处理
ite.remove();
}
}
}
}
package com.nio.server;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import com.nio.user.ServerUser;
import com.nio.user.ServerUserManager;
import com.nio.user.UserData;
import com.ui.server.BootEndInterface;
import com.ui.server.ServerBootFrame;
public class NIOServer implements BootEndInterface {
private ServerBootFrame serverFrame = new ServerBootFrame("服务器端");
private ServerUserManager userManager = null;
HashMap<String, String> hmClient = new HashMap<String, String>();
Vector<String> client = new Vector<String>();
int count = 0;
private static NIOServer nioServer = null;
public NIOServer() {
serverFrame.showFrame();
serverFrame.bootingServer(this);
serverFrame.endingServer(this);
serverFrame.closeWindow(this);
nioServer = this;
}
// 通道管理器
private Selector selector;
/**
* 获得一个ServerSocket通道,并对该通道做一些初始化的工作
*
* @param port
* 绑定的端口号
* @throws IOException
*/
public void initServer(int port) throws IOException {
serverFrame.appendStringTojtaState("服务器(NIO机制)启动中......\n");
// 获得一个ServerSocket通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
// 设置通道为非阻塞
serverChannel.configureBlocking(false);
// 将该通道对应的ServerSocket绑定到port端口
serverChannel.socket().bind(new InetSocketAddress(port));
// 获得一个通道管理器
this.selector = Selector.open();
// 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,
// 当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
//System.out.println("serverChannel 0?" + serverChannel);
}
/**
* 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理
*
* @throws IOException
*/
@SuppressWarnings("unchecked")
public void listen() throws IOException {
// System.out.println("服务端启动成功!");
serverFrame.appendStringTojtaState("服务器(NIO机制)启动成功......\n");
// 轮询访问selector
while (true) {
// 当注册的事件到达时,方法返回;否则,该方法会一直阻塞
selector.select();
// 获得selector中选中的项的迭代器,选中的项为注册的事件
Iterator<?> ite = this.selector.selectedKeys().iterator();
while (ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
// 客户端请求连接事件
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
// 获得和客户端连接的通道
SocketChannel channel = server.accept();
System.out.println("channel A?" + channel);
// 设置成非阻塞
channel.configureBlocking(false);
// 在这里可以给客户端发送信息哦
// channel.write(ByteBuffer.wrap(new
// String("向客户端发送了一条信息").getBytes()));
// 在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。
channel.register(this.selector, SelectionKey.OP_READ);
// 添加一个玩家对象
UserData userData = new UserData();
userData.lineState = 1;
userData.channel = channel;
userManager.addUser(userData);
} else if (key.isReadable()) {
ServerUser serverUser = userManager
.getUser((SocketChannel) key.channel());
// 读取数据失败
if (!serverUser.read()) {
serverUser.clean();
key.channel().close();
}
}
// 删除已选的key,以防重复处理
ite.remove();
}
}
}
/**
* 启动服务端测试
*
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new NIOServer();
}
@Override
public void boot() {
userManager = ServerUserManager.instance();
userManager.initUsers();
serverFrame.appendStringTojtaState("创建玩家内存数据对象成功...\n");
new Thread(new Runnable() {
@Override
public void run() {
try {
NIOServer.this.initServer(5555);
NIOServer.this.listen();
} catch (Exception e) {
serverFrame.appendStringTojtaState("服务器启动失败......\n");
}
}
}).start();
//服务端主逻辑处理
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
Thread.sleep(1);
userManager.run();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
@Override
public void end() {
if (selector != null) {
try {
selector.close();
selector = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.exit(0);
}
public void solveMsg(String message) {
try {
System.out.println(message);
// 对消息进行分析
String msg[] = message.split("#");
if (msg[0].equals("AddUser") == true) {
hmClient.put(msg[1], msg[2]);
sendUsersToOneUser(msg[1]);
if (likeThisName(msg[1]))// 如果出现同名用户,则在用户名后面添加数字来区分
{
msg[1] = msg[1] + count;
}
client.add(msg[1]);
serverFrame.appendStringTojtaState(msg[1] + "上线...\n");
sendMessageToAllUsers(
"AddUser" + "#" + msg[1] + "#" + hmClient.get(msg[1]),
msg[1]);
} else if (msg[0].equals("UserQuit") == true) {
sendMessageToAllUsers("UserQuit" + "#" + msg[1] + "#"
+ hmClient.get(msg[1]), msg[1]);
serverFrame.appendStringTojtaState(msg[1] + "离线...\n");
deleteKeyValue(msg[1]);
client.remove(msg[1]);
// 应该删除vecUser容器中的对应的Socket对象
} else if (msg[0].equals("Message") == true) { // 如果将消息发送给特定用户
if (msg[1].equals("One") == true) {
sendMessageToOneUser("Message" + "#" + msg[2] + "#"
+ msg[6], msg[4]);
} else// 将消息发送给全部用户
{
sendMessageToAllUsers("Message" + "#" + msg[2] + "#"
+ msg[4], msg[2]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendMessageToAllUsers(String msg, String notSendToThisUserName) throws UnsupportedEncodingException {
ServerUser lstUsers[] = userManager.getUsers();
for (int i = 0; i < lstUsers.length; i++) {
if (lstUsers[i].channel != null) {
String address = lockOut(""
+ lstUsers[i].channel.socket().getRemoteSocketAddress());
if ( !address.equals(hmClient.get(notSendToThisUserName)) ) {
lstUsers[i].write(msg.getBytes("utf-8"));
}
}
}
}
public void sendMessageToOneUser(String msg, String sendToThisUserName) throws UnsupportedEncodingException {
ServerUser lstUsers[] = userManager.getUsers();
for (int i = 0; i < lstUsers.length; i++) {
if (lstUsers[i].channel != null) {
String address = lockOut(""
+ lstUsers[i].channel.socket().getRemoteSocketAddress());
if ( address.equals(hmClient.get(sendToThisUserName)) ) {
lstUsers[i].write(msg.getBytes("utf-8"));
break;
}
}
}
}
// 方法完成将在线用户添给用户的下拉表中
public void sendUsersToOneUser(String newUserName) throws UnsupportedEncodingException {
Iterator<String> it = client.listIterator();
for (; it.hasNext();) {
String name = it.next();
String ipAndPort = hmClient.get(name);
sendMessageToOneUser("OnlyAddUser" + "#" + name + "#" + ipAndPort,
newUserName);
}
}
// 将键值对添加到hmClient哈希表中
public void createKeyValue(String userName, String socketAddress) {
hmClient.put(userName, socketAddress);
}
// 从哈希表中删除指定键值对(键为:userName);
public void deleteKeyValue(String userName) {
hmClient.remove(userName);
}
// 将字符串前面的斜杠去掉
public String lockOut(String socketAddress) {
return socketAddress.substring(1, socketAddress.length());
}
// 如果client容器中存放的用户名出现相似用户,则用户名后面添加一个数字
public boolean likeThisName(String thisName) {
count = 0;
for (Iterator it = client.listIterator(); it.hasNext();) {
String temp = (String) it.next();
if (temp.startsWith(thisName) == true) {
count++;
}
}
if (count > 0)
return true;
else
return false;
}
public static void handleMessage(String msg) {
// System.out.println("服务端收到信息:" + msg);
nioServer.solveMsg(msg);
}
}