Main 简单群聊

来源:互联网 发布:教学实训软件 编辑:程序博客网 时间:2024/04/30 23:28

转:http://blog.csdn.net/ibm_hoojo/article/details/7817303

spring集成mina,包含心跳检测,实现服务端主动推送:http://blog.csdn.net/smile326/article/details/51912141

 Apache Mina - SSL配置: http://zjumty.iteye.com/blog/1885453




pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.test</groupId><artifactId>MinaTest</artifactId><version>0.0.1-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><mina.version>2.0.16</mina.version><mina.spring.version>1.1.7</mina.spring.version><spring-version>4.3.2.RELEASE</spring-version><version.log4j>1.2.17</version.log4j><version.slf4j.api>1.7.21</version.slf4j.api><version.slf4j.log4j12>1.7.21</version.slf4j.log4j12><version.slf4j.jcl.over.slf4j>1.7.21</version.slf4j.jcl.over.slf4j></properties><dependencies><!-- mina --><dependency><groupId>org.apache.mina</groupId><artifactId>mina-core</artifactId><version>${mina.version}</version></dependency><dependency><groupId>org.apache.mina</groupId><artifactId>mina-integration-beans</artifactId><version>${mina.version}</version></dependency><dependency><groupId>org.apache.mina</groupId><artifactId>mina-integration-spring</artifactId><version>${mina.spring.version}</version></dependency><!-- Logging --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${version.slf4j.api}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>${version.slf4j.jcl.over.slf4j}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${version.slf4j.log4j12}</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${version.log4j}</version></dependency><!-- spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring-version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring-version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring-version}</version></dependency></dependencies></project>

服务器端

package com.test.server;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.charset.Charset;import org.apache.mina.core.service.IoAcceptor;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.codec.textline.TextLineCodecFactory;import org.apache.mina.filter.logging.LoggingFilter;import org.apache.mina.filter.logging.MdcInjectionFilter;import org.apache.mina.transport.socket.nio.NioSocketAcceptor;/** * cmd telnet 127.0.0.1 9123 *  * * @author Administrator * */public class MainServer {public static void main(String[] args) throws IOException {// 使用IoAcceptor来接收客户端的请求IoAcceptor acceptor = new NioSocketAcceptor();// 加入内置的LoggingFilter,用户打印出一个请求过程中的信息acceptor.getFilterChain().addLast("logger", new LoggingFilter());// 使用Mina提供的ProtocolFilter来对消息进行编码和解码,使用Mina提供的TextLineCodecFactory对消息进行分行处理acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));MdcInjectionFilter mdcInjectionFilter = new MdcInjectionFilter();acceptor.getFilterChain().addLast("mdc", mdcInjectionFilter);// 设置消息处理器,当接收到消息时,可以进行相应的业务操作acceptor.setHandler(new ChatProtocolHandler());// 配置buffer大小acceptor.getSessionConfig().setReadBufferSize(2048);// 如果Session在指定时间内没有事情做(读/写),那么就出发Handlerd的sessionIdle方法acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 1);// 绑定好监听的端口acceptor.bind(new InetSocketAddress(9123));}}

package com.test.server;import java.util.Collections;import java.util.HashSet;import java.util.Set;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.logging.MdcInjectionFilter;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class ChatProtocolHandler extends IoHandlerAdapter {private final static Logger LOGGER = LoggerFactory.getLogger(ChatProtocolHandler.class);private final Set<IoSession> sessions = Collections.synchronizedSet(new HashSet<IoSession>());private final Set<String> users = Collections.synchronizedSet(new HashSet<String>());@Overridepublic void sessionIdle(IoSession session, IdleStatus status) throws Exception {LOGGER.info("idle");}@Overridepublic void exceptionCaught(IoSession session, Throwable cause) throws Exception {LOGGER.warn("Unexpected exception.", cause);// Close connection when unexpected exception is caught.session.closeNow();}@Overridepublic void messageReceived(IoSession session, Object message) throws Exception {String msg = message.toString();// 获取客户端发来的消息LOGGER.info("收到客户端消息:" + msg);String result[] = msg.split(" ");String theCommand = result[0];ChatCommand command = ChatCommand.valueof(theCommand);String user = (String) session.getAttribute("user");switch (command.toInt()) {case ChatCommand.QUIT:session.write("QUIT OK");session.closeOnFlush();LOGGER.info("Session closed");return;case ChatCommand.LOGIN:if (user != null) {session.write(user + "已经登录");return;}if (result.length == 2) {user = result[1];} else {session.write("LOGIN ERROR invalid login command.");return;}// check if the username is already usedif (users.contains(user)) {session.write("LOGIN ERROR the name " + user + " is already used.");return;}sessions.add(session);session.setAttribute("user", user);MdcInjectionFilter.setProperty(session, "user", user);// Allow all usersusers.add(user);session.write("LOGIN OK");broadcast(user + " 上线。。。");break;case ChatCommand.BROADCAST:if (result.length == 2) {broadcast(user + ": " + result[1]);}break;default:LOGGER.info("Unhandled command: " + command);break;}}private void broadcast(String msg) {// TODO Auto-generated method stubsynchronized (sessions) {for (IoSession session : sessions) {if (session.isConnected()) {session.write(msg);}}}}@Overridepublic void sessionClosed(IoSession session) throws Exception {String user = (String) session.getAttribute("user");users.remove(session);sessions.remove(session);broadcast(user + "下线。。。");}public boolean isChatUser(String name) {return users.contains(name);}public int getNumberOfUsers() {return users.size();}public void kick(String name) {synchronized (sessions) {for (IoSession session : sessions) {if (name.equals(session.getAttribute("user"))) {session.closeNow();break;}}}}}

package com.test.client;import java.net.InetSocketAddress;import java.nio.charset.Charset;import org.apache.mina.core.future.ConnectFuture;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.codec.textline.TextLineCodecFactory;import org.apache.mina.filter.logging.LoggingFilter;import org.apache.mina.filter.logging.MdcInjectionFilter;import org.apache.mina.transport.socket.SocketConnector;import org.apache.mina.transport.socket.nio.NioSocketConnector;public class MinaClient {private SocketConnector connector;private IoSession session;private ConnectFuture future;private String name;private static final long CONNECT_TIMEOUT = 30 * 1000L; // 30 secondsprivate static final String HOSTNAME = "127.0.0.1";private static final int PORT = 1234;public boolean connect(String name) {if (session != null && session.isConnected()) {throw new IllegalStateException("Already connected.Disconnect first");}this.name = name;try {// TODO: handle exception// 创建一个socket连接connector = new NioSocketConnector();// 设置连接超时时间connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);connector.getFilterChain().addLast("mdc", new MdcInjectionFilter());// 添加编码过滤器 处理乱码、编码问题connector.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// 日志connector.getFilterChain().addLast("logger", new LoggingFilter());// 消息核心处理器connector.setHandler(new ClientMessageHandlerAdapter());future = connector.connect(new InetSocketAddress(HOSTNAME, PORT));// 等待连接建立future.awaitUninterruptibly();if (!future.isConnected()) {return false;}// 连接建立后返回会话sessionsession = future.getSession();login();return true;} catch (Exception e) {return false;}}public void login() {session.write("LOGIN " + name);}class ClientMessageHandlerAdapter extends IoHandlerAdapter {public void messageReceived(IoSession session, Object message) throws Exception {String content = message.toString();System.out.println("client receive a message is : " + content);}public void messageSent(IoSession session, Object message) throws Exception {System.out.println("messageSent 客户端发送消息:" + message);}@Overridepublic void exceptionCaught(IoSession session, Throwable cause) throws Exception {System.out.println("服务器发生异常: {}" + cause.getMessage());}}public void send(String message) {if("quit".equals(message.toLowerCase())){session.write(message);}else{session.write("BROADCAST " + message);}}public void broadcast(String message) {try {for (int i = 0; i < 1000000; i++) {session.write("BROADCAST " + message + i);}} catch (Exception e) {e.printStackTrace();}}public void quit() {if (session != null) {if (session.isConnected()) {session.write("quit");// Wait until the chat ends.session.getCloseFuture().awaitUninterruptibly();}session.closeNow();}}public SocketConnector getConnector() {return connector;}public IoSession getSession() {return session;}}

服务器端spring整合
serverContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"><!-- This makes it possible to specify java.net.SocketAddress values (e.g. :1234 below) as Strings. They will be converted into java.net.InetSocketAddress objects by Spring. --><bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"><property name="customEditors"><map><entry key="java.net.SocketAddress"value="org.apache.mina.integration.beans.InetSocketAddressEditor"></entry></map></property></bean><!-- The IoHandler implementation --><bean id="chatHandler" class="com.test.server.ChatProtocolHandler" /><!-- the IoFilters --><bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" /><bean id="mdcInjectionFilter" class="org.apache.mina.filter.logging.MdcInjectionFilter"><constructor-arg value="remoteAddress" /></bean><bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter"><constructor-arg><bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" /></constructor-arg></bean><bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" /><!-- The non-SSL filter chain. --><bean id="filterChainBuilder"class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder"><property name="filters"><map><entry key="executor" value-ref="executorFilter" /><entry key="mdcInjectionFilter" value-ref="mdcInjectionFilter" /><entry key="codecFilter" value-ref="codecFilter" /><entry key="loggingFilter" value-ref="loggingFilter" /></map></property></bean><!-- The IoAcceptor which binds to port 1234 --><bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"init-method="bind" destroy-method="unbind"><property name="defaultLocalAddress" value=":1234" /><property name="handler" ref="chatHandler" /><property name="reuseAddress" value="true" /><property name="filterChainBuilder" ref="filterChainBuilder" /></bean><bean id="sessionConfig" factory-bean="ioAcceptor" factory-method="getSessionConfig"><property name="bothIdleTime" value="10" /><!-- acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,10) --><property name="readBufferSize" value="2048" /><!--acceptor.getSessionConfig().setReadBufferSize(2048); --></bean></beans>

SpringMain.java
/* *  Licensed to the Apache Software Foundation (ASF) under one *  or more contributor license agreements.  See the NOTICE file *  distributed with this work for additional information *  regarding copyright ownership.  The ASF licenses this file *  to you under the Apache License, Version 2.0 (the *  "License"); you may not use this file except in compliance *  with the License.  You may obtain a copy of the License at * *    http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, *  software distributed under the License is distributed on an *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *  KIND, either express or implied.  See the License for the *  specific language governing permissions and limitations *  under the License. * */package com.test.server;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringMain {public static void main(String[] args) throws Exception {getApplicationContext();System.out.println("Listening ...");}public static ConfigurableApplicationContext getApplicationContext() {return new ClassPathXmlApplicationContext("classpath:serverContext.xml");}}

客户端
package com.test.client;import java.net.InetSocketAddress;import java.nio.charset.Charset;import org.apache.mina.core.future.ConnectFuture;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.codec.textline.TextLineCodecFactory;import org.apache.mina.filter.logging.LoggingFilter;import org.apache.mina.filter.logging.MdcInjectionFilter;import org.apache.mina.transport.socket.SocketConnector;import org.apache.mina.transport.socket.nio.NioSocketConnector;public class MinaClient {private SocketConnector connector;private IoSession session;private ConnectFuture future;private String name;private static final long CONNECT_TIMEOUT = 30 * 1000L; // 30 secondsprivate static final String HOSTNAME = "127.0.0.1";private static final int PORT = 1234;public boolean connect(String name) {if (session != null && session.isConnected()) {throw new IllegalStateException("Already connected.Disconnect first");}this.name = name;try {// TODO: handle exception// 创建一个socket连接connector = new NioSocketConnector();// 设置连接超时时间connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);connector.getFilterChain().addLast("mdc", new MdcInjectionFilter());// 添加编码过滤器 处理乱码、编码问题connector.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// 日志connector.getFilterChain().addLast("logger", new LoggingFilter());// 消息核心处理器connector.setHandler(new ClientMessageHandlerAdapter());future = connector.connect(new InetSocketAddress(HOSTNAME, PORT));// 等待连接建立future.awaitUninterruptibly();if (!future.isConnected()) {return false;}// 连接建立后返回会话sessionsession = future.getSession();login();return true;} catch (Exception e) {return false;}}public void login() {session.write("LOGIN " + name);}class ClientMessageHandlerAdapter extends IoHandlerAdapter {public void messageReceived(IoSession session, Object message) throws Exception {String content = message.toString();System.out.println("client receive a message is : " + content);}public void messageSent(IoSession session, Object message) throws Exception {System.out.println("messageSent 客户端发送消息:" + message);}@Overridepublic void exceptionCaught(IoSession session, Throwable cause) throws Exception {System.out.println("服务器发生异常: {}" + cause.getMessage());}}public void send(String message) {if("quit".equals(message.toLowerCase())){session.write(message);}else{session.write("BROADCAST " + message);}}public void broadcast(String message) {try {for (int i = 0; i < 1000000; i++) {session.write("BROADCAST " + message + i);}} catch (Exception e) {e.printStackTrace();}}public void quit() {if (session != null) {if (session.isConnected()) {session.write("quit");// Wait until the chat ends.session.getCloseFuture().awaitUninterruptibly();}session.closeNow();}}public SocketConnector getConnector() {return connector;}public IoSession getSession() {return session;}}

package com.test.client;import java.util.Scanner;public class RunClient {public static void main(String[] args) {MinaClient client = new MinaClient();System.out.println("请输入用户名:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();if (client.connect(name)) {while (scanner.hasNext()) {//client.send(scanner.next());client.broadcast(scanner.next());}}}}

http://download.csdn.net/detail/u014695188/9738655


0 0
原创粉丝点击