├── .settings ├── org.eclipse.wst.jsdt.ui.superType.name ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.core.resources.prefs ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.wst.common.component ├── .jsdtscope └── org.eclipse.jdt.core.prefs ├── WebContent ├── META-INF │ └── MANIFEST.MF ├── WEB-INF │ ├── lib │ │ ├── spring.jar │ │ ├── antlr-2.7.7.jar │ │ ├── c3p0-0.9.2.1.jar │ │ ├── dom4j-1.6.1.jar │ │ ├── log4j-1.2.17.jar │ │ ├── servlet-api.jar │ │ ├── commons-io-2.4.jar │ │ ├── proxool-0.8.3.jar │ │ ├── proxool-0.9.1.jar │ │ ├── proxool-cglib.jar │ │ ├── mina-core-2.0.7.jar │ │ ├── slf4j-api-1.6.1.jar │ │ ├── slf4j-api-1.7.7.jar │ │ ├── ehcache-core-2.4.3.jar │ │ ├── javassist-3.18.1-GA.jar │ │ ├── protobuf-java-2.5.0.jar │ │ ├── commons-logging-1.1.3.jar │ │ ├── jboss-logging-3.1.3.GA.jar │ │ ├── commons-fileupload-1.3.1.jar │ │ ├── hibernate-c3p0-4.3.8.Final.jar │ │ ├── hibernate-core-4.3.8.Final.jar │ │ ├── hibernate-ehcache-4.3.8.Final.jar │ │ ├── hibernate-proxool-4.3.8.Final.jar │ │ ├── mchange-commons-java-0.2.3.4.jar │ │ ├── hibernate-jpa-2.1-api-1.0.0.Final.jar │ │ ├── mysql-connector-java-5.1.2-beta-bin.jar │ │ ├── org.springframework.asm-3.1.1.RELEASE.jar │ │ ├── org.springframework.beans-3.1.1.RELEASE.jar │ │ ├── org.springframework.core-3.1.1.RELEASE.jar │ │ ├── hibernate-commons-annotations-4.0.5.Final.jar │ │ ├── jboss-transaction-api_1.2_spec-1.0.0.Final.jar │ │ └── org.springframework.instrument.tomcat-3.1.1.RELEASE.jar │ ├── dropTable.sql │ ├── web.xml │ └── createTable.sql ├── protobuf │ ├── OffLineMsg.proto │ ├── GetPersonalInfoMsg.proto │ ├── gen.bat │ ├── ReceiveChatMsg.proto │ ├── KeepAliveMsg.proto │ ├── UserData.proto │ ├── LogoutMsg.proto │ ├── GroupData.proto │ ├── AddFriendMsg.proto │ ├── ChangeFriendMsg.proto │ ├── DeleteFriendMsg.proto │ ├── LoginMsg.proto │ ├── SendChatMsg.proto │ ├── CreateGroupChatMsg.proto │ ├── PersonalSettingsMsg.proto │ ├── GetGroupInfoMsg.proto │ ├── GetUserInfoMsg.proto │ ├── RegisterMsg.proto │ ├── ChatData.proto │ ├── ChangeGroupMsg.proto │ └── ProtoHead.proto └── TestHttp.html ├── src ├── server_HTTP │ ├── ServletClient.java │ └── MyHttpServer.java ├── protocol │ └── Msg │ │ ├── OffLineMsg.java │ │ └── GetPersonalInfoMsg.java ├── exception │ ├── NoIpException.java │ └── MyException.java ├── observer │ ├── ObserverMessage.java │ └── ObserverMessage_Login.java ├── server │ ├── WaitClientResponseCallBack.java │ ├── Test2.java │ ├── ClientUser.java │ ├── Test.java │ ├── ResourcePath.java │ ├── WaitClientResponse.java │ ├── PacketFromServer.java │ ├── MinaDecoder.java │ ├── MinaEncoder.java │ ├── ClientRequest_Dispatcher.java │ ├── Server.java │ ├── NetworkPacket.java │ ├── MinaServerHandle.java │ ├── MyLogger.java │ └── ServerNetwork.java ├── model │ ├── ResultCode.java │ ├── HibernateSessionFactory.java │ ├── Group.java │ ├── User.java │ ├── test.java │ ├── Chatting.java │ └── HibernateDataOperation.java ├── test │ ├── HelloWorld1.java │ ├── TestLog1.java │ ├── TestMessage.java │ ├── Client111.java │ ├── test.java │ ├── ConnectionPoolTest.java │ ├── TestHibernate.java │ └── Server111.java ├── tools │ ├── MyListener.java │ ├── MyTask.java │ ├── GetImage.java │ ├── DataTypeTranslater.java │ ├── Debug.java │ ├── AutoResponseClient.java │ ├── HttpClient.java │ └── FormHandler.java ├── JUnit │ ├── TestGetGroupInfo.java │ ├── TestDoubleLogin.java │ ├── TestAutoResponse.java │ ├── TestLogout.java │ ├── TestGetUserInfo.java │ ├── TestLogin.java │ ├── TestDeleteFriend.java │ ├── TestAddFriend.java │ ├── TestRegister.java │ ├── TestGetPersonalInfo.java │ ├── TestPersonalSettings.java │ ├── TestCreateGroupChatting.java │ ├── TestSendGroupChatting.java │ ├── ClientSocket.java │ └── TestChangeGroup.java └── hibernate.cfg.xml ├── output1.txt ├── LoggerRule.xml ├── .gitignore ├── Log4JConfig.properties ├── LICENSE ├── .project ├── Java └── MiniWechat │ ├── .project │ └── bin │ └── .project ├── README.md ├── .classpath.orig ├── .classpath └── applicationContext.xml /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /WebContent/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /src/server_HTTP/ServletClient.java: -------------------------------------------------------------------------------- 1 | package server_HTTP; 2 | 3 | public class ServletClient { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/spring.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/spring.jar -------------------------------------------------------------------------------- /src/protocol/Msg/OffLineMsg.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/src/protocol/Msg/OffLineMsg.java -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/client/SocketClientTest.java=UTF-8 3 | -------------------------------------------------------------------------------- /WebContent/protobuf/OffLineMsg.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/protobuf/OffLineMsg.proto -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/antlr-2.7.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/antlr-2.7.7.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/c3p0-0.9.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/c3p0-0.9.2.1.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/dom4j-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/dom4j-1.6.1.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/log4j-1.2.17.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/log4j-1.2.17.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/servlet-api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/servlet-api.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/commons-io-2.4.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/proxool-0.8.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/proxool-0.8.3.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/proxool-0.9.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/proxool-0.9.1.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/proxool-cglib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/proxool-cglib.jar -------------------------------------------------------------------------------- /src/protocol/Msg/GetPersonalInfoMsg.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/src/protocol/Msg/GetPersonalInfoMsg.java -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/mina-core-2.0.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/mina-core-2.0.7.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/slf4j-api-1.7.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/slf4j-api-1.7.7.jar -------------------------------------------------------------------------------- /WebContent/protobuf/GetPersonalInfoMsg.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/protobuf/GetPersonalInfoMsg.proto -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/ehcache-core-2.4.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/ehcache-core-2.4.3.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/javassist-3.18.1-GA.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/javassist-3.18.1-GA.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/protobuf-java-2.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/protobuf-java-2.5.0.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/commons-logging-1.1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/commons-logging-1.1.3.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/jboss-logging-3.1.3.GA.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/jboss-logging-3.1.3.GA.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/commons-fileupload-1.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/commons-fileupload-1.3.1.jar -------------------------------------------------------------------------------- /output1.txt: -------------------------------------------------------------------------------- 1 | DEBUG - Here is some DEBUG 2 | INFO - Here is some INFO 3 | WARN - Here is some WARN 4 | ERROR - Here is some ERROR 5 | FATAL - Here is some FATAL 6 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/hibernate-c3p0-4.3.8.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/hibernate-c3p0-4.3.8.Final.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/hibernate-core-4.3.8.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/hibernate-core-4.3.8.Final.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/hibernate-ehcache-4.3.8.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/hibernate-ehcache-4.3.8.Final.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/hibernate-proxool-4.3.8.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/hibernate-proxool-4.3.8.Final.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/mchange-commons-java-0.2.3.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/mchange-commons-java-0.2.3.4.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/mysql-connector-java-5.1.2-beta-bin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/mysql-connector-java-5.1.2-beta-bin.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/org.springframework.asm-3.1.1.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/org.springframework.asm-3.1.1.RELEASE.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/org.springframework.beans-3.1.1.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/org.springframework.beans-3.1.1.RELEASE.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/org.springframework.core-3.1.1.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/org.springframework.core-3.1.1.RELEASE.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/hibernate-commons-annotations-4.0.5.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/hibernate-commons-annotations-4.0.5.Final.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/jboss-transaction-api_1.2_spec-1.0.0.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/jboss-transaction-api_1.2_spec-1.0.0.Final.jar -------------------------------------------------------------------------------- /WebContent/protobuf/gen.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem 查找文件 3 | for /f "delims=" %%i in ('dir /b ".\*.proto"') do echo %%i 4 | for /f "delims=" %%i in ('dir /b/a ".\*.proto"') do protoc --java_out=./ %%i 5 | pause -------------------------------------------------------------------------------- /src/exception/NoIpException.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | /** 4 | * 找不到IP(Socket)时抛出 5 | * @author Feng 6 | * 7 | */ 8 | public class NoIpException extends Exception { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.1.1.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Feng14/MiniWeChat-Server/HEAD/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.1.1.RELEASE.jar -------------------------------------------------------------------------------- /WebContent/protobuf/ReceiveChatMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "ChatData.proto"; 5 | 6 | message ReceiveChatSync{ 7 | repeated ChatItem chatData = 1; 8 | } 9 | -------------------------------------------------------------------------------- /WebContent/protobuf/KeepAliveMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message KeepAliveSyncPacket{ 6 | optional int32 a=1; 7 | optional bool b=2; 8 | optional string c=3; 9 | } -------------------------------------------------------------------------------- /src/observer/ObserverMessage.java: -------------------------------------------------------------------------------- 1 | package observer; 2 | 3 | /** 4 | * 消息机制的父类 5 | * @author Feng 6 | * 7 | */ 8 | public class ObserverMessage { 9 | public enum Type {Login}; 10 | public Type type; 11 | } 12 | -------------------------------------------------------------------------------- /src/server/WaitClientResponseCallBack.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | /** 4 | * 服务器向客户端发消息,等待客户端回复,在客户端不存在,准备删除前的回调 5 | * @author Feng 6 | * 7 | */ 8 | public interface WaitClientResponseCallBack { 9 | 10 | void beforeDelete(); 11 | } 12 | -------------------------------------------------------------------------------- /WebContent/protobuf/UserData.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Data"; 4 | 5 | message UserItem{ 6 | required string userId = 1; 7 | required string userName = 2; 8 | optional int32 headIndex = 3; 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /LoggerRule.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | False 4 | 5 | KEEP_ALIVE_SYNC 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebContent/protobuf/LogoutMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message LogoutReq{ 6 | 7 | } 8 | 9 | message LogoutRsp{ 10 | enum ResultCode{ 11 | SUCCESS = 0; 12 | FAIL = 1; 13 | } 14 | 15 | required ResultCode resultCode = 1; 16 | } 17 | -------------------------------------------------------------------------------- /WebContent/protobuf/GroupData.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Data"; 4 | 5 | message GroupItem{ 6 | required string groupId = 1; 7 | required string groupName = 2; 8 | required string createrUserId = 3; 9 | repeated string memberUserId = 4; 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/model/ResultCode.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public enum ResultCode { 4 | NULL,SUCCESS,FAIL,USEREXIST;//NULL代表初始状态 5 | private ResultCode code; 6 | 7 | public void setCode(ResultCode code){ 8 | this.code = code; 9 | } 10 | public ResultCode getCode(){ 11 | return this.code; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /WebContent/protobuf/AddFriendMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message AddFriendReq{ 6 | required string friendUserId = 1; 7 | } 8 | 9 | message AddFriendRsp{ 10 | enum ResultCode{ 11 | SUCCESS = 0; 12 | FAIL = 1; 13 | } 14 | required ResultCode resultCode = 1; 15 | } -------------------------------------------------------------------------------- /WebContent/protobuf/ChangeFriendMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "UserData.proto"; 5 | 6 | message ChangeFriendSync{ 7 | enum ChangeType{ 8 | ADD = 0; 9 | DELETE = 1; 10 | UPDATE = 2; 11 | } 12 | required ChangeType changeType = 1; 13 | required UserItem userItem = 2; 14 | } -------------------------------------------------------------------------------- /WebContent/protobuf/DeleteFriendMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message DeleteFriendReq{ 6 | required string friendUserId = 1; 7 | } 8 | 9 | message DeleteFriendRsp{ 10 | enum ResultCode{ 11 | SUCCESS = 0; 12 | FAIL = 1; 13 | } 14 | required ResultCode resultCode = 1; 15 | } -------------------------------------------------------------------------------- /WebContent/protobuf/LoginMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message LoginReq{ 6 | required string userId= 1; 7 | required string userPassword= 2; 8 | } 9 | message LoginRsp{ 10 | enum ResultCode{ 11 | SUCCESS = 0; 12 | FAIL = 1; 13 | } 14 | 15 | required ResultCode resultCode = 1; 16 | } 17 | -------------------------------------------------------------------------------- /WebContent/protobuf/SendChatMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "ChatData.proto"; 5 | 6 | message SendChatReq{ 7 | required ChatItem chatData = 1; 8 | 9 | } 10 | message SendChatRsp{ 11 | enum ResultCode{ 12 | SUCCESS = 0; 13 | FAIL = 1; 14 | } 15 | 16 | required ResultCode resultCode = 1; 17 | } 18 | -------------------------------------------------------------------------------- /src/server/Test2.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | public class Test2 { 4 | 5 | public Test test; 6 | 7 | public Test getTest() { 8 | return test; 9 | } 10 | 11 | public void setTest(Test test) { 12 | this.test = test; 13 | System.out.println(test.fuck); 14 | } 15 | 16 | 17 | public void fuck(){ 18 | System.out.println(test.fuck); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/server/ClientUser.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import org.apache.mina.core.session.IoSession; 4 | 5 | /** 6 | * 服务器端对客户端用户的状态记录 7 | * @author Feng 8 | * 9 | */ 10 | public class ClientUser { 11 | public IoSession ioSession; 12 | public boolean onLine = true; 13 | public String userId; 14 | 15 | public ClientUser(IoSession ioSession){ 16 | this.ioSession = ioSession; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WebContent/protobuf/CreateGroupChatMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "ChatData.proto"; 5 | 6 | message CreateGroupChatReq{ 7 | repeated string userId = 1; 8 | 9 | } 10 | message CreateGroupChatRsp{ 11 | enum ResultCode{ 12 | SUCCESS = 0; 13 | FAIL = 1; 14 | } 15 | 16 | required ResultCode resultCode = 1; 17 | required int32 groupChatId = 2; 18 | } 19 | -------------------------------------------------------------------------------- /WebContent/protobuf/PersonalSettingsMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message PersonalSettingsReq{ 6 | optional string userName = 1 ; 7 | optional string userPassword = 2 ; 8 | optional int32 headIndex = 3 ; 9 | } 10 | 11 | message PersonalSettingsRsp{ 12 | enum ResultCode{ 13 | SUCCESS = 0; 14 | FAIL = 1; 15 | } 16 | required ResultCode resultCode = 1; 17 | } -------------------------------------------------------------------------------- /src/observer/ObserverMessage_Login.java: -------------------------------------------------------------------------------- 1 | package observer; 2 | 3 | import org.apache.mina.core.session.IoSession; 4 | 5 | public class ObserverMessage_Login extends ObserverMessage { 6 | public IoSession ioSession; 7 | public String userId; 8 | 9 | public ObserverMessage_Login(IoSession ioSession, String userId){ 10 | type = Type.Login; 11 | this.ioSession = ioSession; 12 | this.userId = userId; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WebContent/protobuf/GetGroupInfoMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "GroupData.proto"; 5 | 6 | message GetGroupInfoReq{ 7 | required string groupId = 1 ; 8 | } 9 | 10 | message GetGroupInfoRsp{ 11 | enum ResultCode{ 12 | SUCCESS = 0;//搜索到群 13 | FAIL = 1;//未搜索到群 14 | GROUP_NOT_EXIST = 2;//群不存在 15 | } 16 | required ResultCode resultCode = 1; 17 | required GroupItem groupItem = 2; 18 | } -------------------------------------------------------------------------------- /WebContent/protobuf/GetUserInfoMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "UserData.proto"; 5 | 6 | message GetUserInfoReq{ 7 | repeated string targetUserId = 1 ; 8 | } 9 | 10 | message GetUserInfoRsp{ 11 | enum ResultCode{ 12 | SUCCESS = 0;//搜索到用户 13 | FAIL = 1;//未搜索到用户 14 | USER_NOT_EXIST = 2;//用户不存在 15 | } 16 | required ResultCode resultCode = 1; 17 | repeated UserItem userItem = 2; 18 | } -------------------------------------------------------------------------------- /WebContent/protobuf/RegisterMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | 5 | message RegisterReq{ 6 | required string userId = 1; 7 | required string userName = 2; 8 | required string userPassword = 3; 9 | } 10 | 11 | message RegisterRsp { 12 | 13 | enum ResultCode{ 14 | SUCCESS = 0; //表示注册成功 15 | USER_EXIST = 1; //表示用户名已存在 16 | } 17 | 18 | required ResultCode resultCode = 1; 19 | } -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WebContent/protobuf/ChatData.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Data"; 4 | 5 | message ChatItem{ 6 | enum ChatType{ 7 | TEXT = 0; 8 | IMAGE = 1; 9 | } 10 | enum TargetType{ 11 | INDIVIDUAL = 0; 12 | GROUP = 1; 13 | SYSTEM = 2; 14 | } 15 | 16 | optional TargetType targetType = 1[default = INDIVIDUAL]; 17 | optional string sendUserId= 2; 18 | required string receiveUserId= 3; 19 | required ChatType chatType= 4; 20 | required string chatBody= 5; 21 | optional int64 date = 6; 22 | } -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/exception/MyException.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | public class MyException extends Exception { 4 | private String message; 5 | 6 | public MyException(String message) { 7 | super(message); 8 | this.message = message; 9 | } 10 | 11 | public String toString(){ 12 | return message + "\n" + getStackStr(getStackTrace()); 13 | } 14 | 15 | public static String getStackStr(StackTraceElement[] stackTraceElements) { 16 | String s = "Stack:\n"; 17 | for (StackTraceElement se : stackTraceElements) 18 | s += se.toString() + "\n"; 19 | return s; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WebContent/TestHttp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Insert title here 6 | 7 | 8 |
9 | 要获取的类型:
10 | 要获取图片的地址:
11 | 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /WebContent/protobuf/ChangeGroupMsg.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol.Msg"; 4 | import "GroupData.proto"; 5 | 6 | message ChangeGroupReq{ 7 | enum ChangeType{ 8 | ADD = 0; 9 | DELETE = 1; 10 | UPDATE_INFO = 2; 11 | } 12 | required string groupId = 1; 13 | required ChangeType changeType = 2; 14 | repeated string userId = 3; 15 | optional string groupName = 4; 16 | } 17 | message ChangeGroupRsp{ 18 | enum ResultCode{ 19 | SUCCESS = 0; 20 | FAIL = 1; 21 | NO_AUTHORITY = 2; 22 | } 23 | required ResultCode resultCode = 1; 24 | } 25 | message ChangeGroupSync{ 26 | required GroupItem groupItem = 1; 27 | } -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.7 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.7 12 | -------------------------------------------------------------------------------- /src/test/HelloWorld1.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServlet; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | public class HelloWorld1 extends HttpServlet { 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 16 | response.setContentType("text/html"); 17 | PrintWriter writer = response.getWriter(); 18 | writer.println("Hello World!"); 19 | } 20 | } -------------------------------------------------------------------------------- /src/tools/MyListener.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import javax.servlet.ServletContextEvent; 4 | import javax.servlet.ServletContextListener; 5 | 6 | public class MyListener implements ServletContextListener { 7 | 8 | private java.util.Timer timer = null; 9 | 10 | public void contextDestroyed(ServletContextEvent event) { 11 | // TODO Auto-generated method stub 12 | 13 | } 14 | 15 | public void contextInitialized(ServletContextEvent event) { 16 | 17 | timer = new java.util.Timer(true); 18 | event.getServletContext().log("定时器已启动。"); 19 | timer.schedule(new MyTask(event.getServletContext(), timer), 0, 5000); 20 | event.getServletContext().log("已经添加任务调度表。"); 21 | 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/server/Test.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.awt.List; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.util.ArrayList; 7 | import java.util.Calendar; 8 | import java.util.Date; 9 | 10 | import org.hibernate.Session; 11 | import model.HibernateSessionFactory; 12 | import model.ResultCode; 13 | import model.User; 14 | 15 | public class Test { 16 | // public static Test test = new Test(); 17 | public int fuck = 123; 18 | 19 | // public static Test getTest() { 20 | // return test; 21 | // } 22 | // 23 | // public static void setTest(Test test) { 24 | // Test.test = test; 25 | // } 26 | 27 | public static void main(String args[]) { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.exe 3 | 4 | # Mobile Tools for Java (J2ME) 5 | .mtj.tmp/ 6 | 7 | # Package Files # 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | /WebContent/protobuf/protocol 14 | /build 15 | *.log 16 | src/server/tttt.java 17 | src/server/tttt.java.BACKUP.11432.java 18 | src/server/tttt.java.BACKUP.14824.java 19 | src/server/tttt.java.BACKUP.17384.java 20 | src/server/tttt.java.BASE.11432.java 21 | src/server/tttt.java.BASE.14824.java 22 | src/server/tttt.java.BASE.17384.java 23 | src/server/tttt.java.LOCAL.11432.java 24 | src/server/tttt.java.LOCAL.14824.java 25 | src/server/tttt.java.LOCAL.17384.java 26 | src/server/tttt.java.REMOTE.11432.java 27 | src/server/tttt.java.REMOTE.14824.java 28 | src/server/tttt.java.REMOTE.17384.java 29 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/dropTable.sql: -------------------------------------------------------------------------------- 1 | #删除group_members中的外键 2 | alter table group_members drop foreign key fk_1; 3 | alter table group_members drop foreign key fk_2; 4 | #删除表user_friends中的外键 5 | alter table user_friends drop foreign key fk_3; 6 | alter table user_friends drop foreign key fk_4; 7 | #删除表chatting_message中的外键 8 | alter table chatting_message drop foreign key fk_5; 9 | alter table chatting_message drop foreign key fk_6; 10 | alter table chatting_message drop foreign key fk_7; 11 | #删除表user_group中的外键 12 | alter table user_group drop foreign key fk_8; 13 | 14 | #删除表chatting_message 15 | drop table if exists chatting_message; 16 | #删除表group_members 17 | drop table if exists group_members; 18 | #删除表user 19 | drop table if exists user; 20 | #删除表user_friends 21 | drop table if exists user_friends; 22 | #删除表user_group 23 | drop table if exists user_group; -------------------------------------------------------------------------------- /src/test/TestLog1.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import org.apache.log4j.FileAppender; 4 | import org.apache.log4j.Level; 5 | import org.apache.log4j.Logger; 6 | import org.apache.log4j.SimpleLayout; 7 | 8 | public class TestLog1 { 9 | static Logger logger = Logger.getLogger(TestLog1.class); 10 | 11 | public static void main(String args[]) { 12 | SimpleLayout layout = new SimpleLayout(); 13 | FileAppender appender = null; 14 | try { 15 | appender = new FileAppender(layout, "d:/output1.txt", false); 16 | } catch (Exception e) { 17 | } 18 | logger.addAppender(appender); 19 | logger.setLevel((Level) Level.DEBUG); 20 | logger.debug("Here is some DEBUG"); 21 | logger.info("Here is some INFO"); 22 | logger.warn("Here is some WARN"); 23 | logger.error("Here is some ERROR"); 24 | logger.fatal("Here is some FATAL"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebContent/protobuf/ProtoHead.proto: -------------------------------------------------------------------------------- 1 | package protocol; 2 | 3 | option java_package = "protocol"; 4 | 5 | enum ENetworkMessage{ 6 | KEEP_ALIVE_SYNC=0; 7 | REGISTER_REQ=1; 8 | REGISTER_RSP=2; 9 | LOGIN_REQ=3; 10 | LOGIN_RSP=4; 11 | PERSONALSETTINGS_REQ=5; 12 | PERSONALSETTINGS_RSP=6; 13 | GET_USERINFO_REQ=7; 14 | GET_USERINFO_RSP=8; 15 | ADD_FRIEND_REQ=9; 16 | ADD_FRIEND_RSP=10; 17 | DELETE_FRIEND_REQ=11; 18 | DELETE_FRIEND_RSP=12; 19 | OFFLINE_SYNC=13; 20 | LOGOUT_REQ=14; 21 | LOGOUT_RSP=15; 22 | GET_PERSONALINFO_REQ=16; 23 | GET_PERSONALINFO_RSP=17; 24 | CHANGE_FRIEND_SYNC=18; 25 | SEND_CHAT_REQ=19; 26 | SEND_CHAT_RSP=20; 27 | RECEIVE_CHAT_SYNC=21; 28 | CREATE_GROUP_CHAT_REQ=22; 29 | CREATE_GROUP_CHAT_RSP=23; 30 | CHANGE_GROUP_REQ=24; 31 | CHANGE_GROUP_RSP=25; 32 | CHANGE_GROUP_SYNC=26; 33 | GET_GROUP_INFO_REQ=27; 34 | GET_GROUP_INFO_RSP=28; 35 | } 36 | -------------------------------------------------------------------------------- /Log4JConfig.properties: -------------------------------------------------------------------------------- 1 | # Set root category priority to info and its only appender to console. 2 | log4j.rootCategory=INFO,console,R 3 | #log4j.debug=true 4 | 5 | # console is set to be a ConsoleAppender using a PatternLayout. 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.Threshold=INFO 8 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.console.layout.ConversionPattern=- %m%n 10 | 11 | # R is set to be a File appender using a PatternLayout. 12 | log4j.appender.R=org.apache.log4j.DailyRollingFileAppender 13 | log4j.appender.R.Append=true 14 | log4j.appender.R.Threshold=INFO 15 | log4j.appender.R.File=logs/miniwechat.log 16 | log4j.appender.R.layout=org.apache.log4j.PatternLayout 17 | log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%c]-[%p] %m%n 18 | log4j.appender.R.DatePattern = '.'yyyy-MM-dd'.log' 19 | -------------------------------------------------------------------------------- /src/server/ResourcePath.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | public class ResourcePath { 4 | /** 5 | * 定义文件路径 6 | */ 7 | 8 | //头像路径 9 | private static String headPath_linux = "miniwechatRes/head/"; 10 | private static String headPath_windows ="d:\\miniwechatRes\\head\\"; 11 | //默认头像路径 12 | private static String headDefaultPath_windows = "d:\\miniwechatRes\\headDefault\\"; 13 | private static String headDefaultPath_linux = "miniwechatRes/headDefault/"; 14 | 15 | public static String getHeadPath(){ 16 | if(System.getProperty("os.name").toLowerCase().indexOf("windows")>=0){ 17 | return headPath_windows; 18 | } 19 | else{ 20 | return headPath_linux; 21 | } 22 | } 23 | 24 | public static String getHeadDefaultPath(){ 25 | if(System.getProperty("os.name").toLowerCase().indexOf("windows")>=0){ 26 | return headDefaultPath_windows; 27 | } 28 | else{ 29 | return headDefaultPath_linux; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/TestMessage.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.InputStream; 4 | import java.util.Observable; 5 | import java.util.Observer; 6 | 7 | import org.xml.sax.InputSource; 8 | 9 | public class TestMessage { 10 | 11 | public static void main(String args[]) { 12 | // A a = new A(); 13 | // B b = new B(a); 14 | // a.x = 3; 15 | // a.notifyObservers(); 16 | int x = 123; 17 | byte y = (byte)x; 18 | System.out.println(y); 19 | int z = (int)y; 20 | System.out.println(z); 21 | 22 | } 23 | } 24 | 25 | class A extends Observable { 26 | public int x=0; 27 | public A() { 28 | 29 | } 30 | public void fuck(){ 31 | setChanged(); 32 | } 33 | } 34 | 35 | class B { 36 | public B(A a) { 37 | a.addObserver(new Observer() { 38 | 39 | @Override 40 | public void update(Observable o, Object arg) { 41 | System.out.println("Fuck you every Where"); 42 | } 43 | }); 44 | a.fuck(); 45 | a.notifyObservers("Fuck"); 46 | } 47 | } -------------------------------------------------------------------------------- /src/server/WaitClientResponse.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.util.Date; 4 | 5 | import org.apache.mina.core.session.IoSession; 6 | 7 | /** 8 | * 这是一个存在“监听Client回复”表中的对象 9 | * @author Feng 10 | * 11 | */ 12 | public class WaitClientResponse { 13 | // long time; 14 | // public byte[] messageHasSent; 15 | public PacketFromServer packetFromServer; 16 | public IoSession ioSession; 17 | public WaitClientResponseCallBack waitClientResponseCallBack; 18 | 19 | public WaitClientResponse(IoSession ioSession, PacketFromServer packetFromServer) { 20 | this.ioSession = ioSession; 21 | this.packetFromServer = packetFromServer; 22 | this.waitClientResponseCallBack = null; 23 | } 24 | 25 | public WaitClientResponse(IoSession ioSession, PacketFromServer packetFromServer, WaitClientResponseCallBack waitClientResponseCallBack) { 26 | this.ioSession = ioSession; 27 | this.packetFromServer = packetFromServer; 28 | this.waitClientResponseCallBack = waitClientResponseCallBack; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/Client111.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.net.UnknownHostException; 8 | 9 | import client.SocketClientTest; 10 | 11 | public class Client111 { 12 | public static final String host = "127.0.0.1"; // 要连接的服务端IP地址 13 | int port = 8081; // 要连接的服务端对应的监听端口 14 | 15 | public static final int HEAD_INT_SIZE = 4; 16 | public Socket socket; 17 | public InputStream inputStream; 18 | public OutputStream outputStream; 19 | 20 | public static void main(String args[]) throws IOException { 21 | new Client111(); 22 | } 23 | 24 | public Client111() throws UnknownHostException, IOException { 25 | link(); 26 | } 27 | 28 | public void link() throws UnknownHostException, IOException { 29 | socket = new Socket(host, port); 30 | inputStream = socket.getInputStream(); 31 | outputStream = socket.getOutputStream(); 32 | 33 | byte[] byteArray = new byte[100]; 34 | while (true) { 35 | inputStream.read(byteArray); 36 | System.out.println(byteArray); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 王选易 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MiniWechat 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.wst.validation.validationbuilder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jem.workbench.JavaEMFNature 31 | org.eclipse.wst.common.modulecore.ModuleCoreNature 32 | org.eclipse.wst.common.project.facet.core.nature 33 | org.eclipse.jdt.core.javanature 34 | org.eclipse.wst.jsdt.core.jsNature 35 | 36 | 37 | -------------------------------------------------------------------------------- /Java/MiniWechat/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MiniWechat 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.wst.validation.validationbuilder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jem.workbench.JavaEMFNature 31 | org.eclipse.wst.common.modulecore.ModuleCoreNature 32 | org.eclipse.wst.common.project.facet.core.nature 33 | org.eclipse.jdt.core.javanature 34 | org.eclipse.wst.jsdt.core.jsNature 35 | 36 | 37 | -------------------------------------------------------------------------------- /Java/MiniWechat/bin/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MiniWechat 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.wst.validation.validationbuilder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jem.workbench.JavaEMFNature 31 | org.eclipse.wst.common.modulecore.ModuleCoreNature 32 | org.eclipse.wst.common.project.facet.core.nature 33 | org.eclipse.jdt.core.javanature 34 | org.eclipse.wst.jsdt.core.jsNature 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/tools/MyTask.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.util.Timer; 4 | import java.util.TimerTask; 5 | 6 | import javax.servlet.ServletContext; 7 | 8 | import org.apache.log4j.Logger; 9 | 10 | public class MyTask extends TimerTask { 11 | private static Logger logger = Logger.getLogger(MyTask.class); 12 | private static boolean isRunning = false; 13 | private ServletContext context = null; 14 | private Timer timer; 15 | 16 | public MyTask(ServletContext context, Timer timer) { 17 | this.context = context; 18 | this.timer = timer; 19 | } 20 | 21 | @Override 22 | public void run() { 23 | 24 | if (!isRunning) { 25 | logger.info("开始执行指定任务."); 26 | // if (C_SCHEDULE_HOUR == c.get(Calendar.HOUR_OF_DAY)) { 27 | isRunning = true; 28 | context.log("开始执行指定任务."); 29 | // TODO 添加自定义的详细任务,以下只是示例 30 | int i = 0; 31 | while (i++ < 10) { 32 | context.log("已完成任务的" + i + "/" + 10); 33 | // System.out.println("已完成任务的" + i + "/" + 1000) ; 34 | } 35 | 36 | isRunning = false; 37 | context.log("指定任务执行结束"); 38 | logger.info("指定任务执行结束"); 39 | timer.cancel(); 40 | // } 41 | } else { 42 | context.log("上一次任务执行还未结束"); 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/test/test.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.util.Calendar; 4 | import java.util.Date; 5 | import java.util.Hashtable; 6 | import java.util.Timer; 7 | import java.util.TimerTask; 8 | import java.util.concurrent.LinkedBlockingQueue; 9 | 10 | import org.apache.log4j.Logger; 11 | 12 | import protocol.Data.ChatData.ChatItem.ChatType; 13 | 14 | import server.ServerModel; 15 | import server.ServerModel_Chatting; 16 | 17 | import model.Chatting; 18 | 19 | public class test { 20 | 21 | public test(){ 22 | // System.out.println(this.getClass().toString()); 23 | Logger logger1 = Logger.getLogger(this.getClass()); 24 | System.out.println(logger1.getName()); 25 | System.out.println(this.getClass().getName().toString()); 26 | System.out.println(logger1 == Logger.getLogger(this.getClass().getName().toString())); 27 | } 28 | 29 | public static void main(String args[]) { 30 | // Hashtable> chattingHashtable = ServerModel_Chatting.instance.chattingHashtable; 31 | // ServerModel_Chatting.instance.addChatting(new Chatting("a", "b", ChatType.TEXT, "Fuck")); 32 | // ServerModel_Chatting.instance.addChatting(new Chatting("c", "d", ChatType.TEXT, "Fuck")); 33 | // ServerModel_Chatting.instance.a(); 34 | 35 | new test(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![项目Logo](http://images.cnblogs.com/cnblogs_com/xiaozefeng/686123/o_Logo.png) 2 | 3 | 4 | #MiniWeChat 5 | 6 | 迷你微信客户端:[MiniWeChat-Client](https://github.com/MrNerverDie/MiniWeChat-Client) 7 | 8 | 后端介绍博客:http://www.cnblogs.com/xiaozefeng/p/mina_wechat_Java.html 9 | 10 | 《迷你微信》是一款仿制微信的手机跨平台应用,服务器端使用J2EE(包括Mina框架、Hibernate、Spring、Protobuf)实现,包含了通讯录,个人资料,单对单聊天,群聊等功能。 11 | 12 | ###项目需求 13 | 14 | JDK版本 = 1.7 MySql版本 = 5.1 15 | 16 | ###如何部署 17 | 18 | - 数据库配置 19 | 20 | 在hibernat.cfg.xml中查看、更改数据库连接的端口号、数据库名、用户名和密码 21 | ``` 22 | 23 | com.mysql.jdbc.Driver 24 | 25 | jdbc:mysql://127.0.0.1:3306/MiniWechat?useUnicode=true&characterEncoding=UTF-8 26 | 27 | root 28 | root 29 | ``` 30 | - 创建数据库 31 | 32 | 在Java项目中的/WebContent/WEB-INF路径下有createTable.sql和dropTable两个建表和删表的sql语句,直接运行即可 33 | 34 | - 启动服务器端程序 35 | 36 | 将项目代码打jar包(要将第三方包一起打入),并把根目录下的applicationContext.xml和Log4JConfig.properties和LoggerRule.xml三个配置文件放在jar包相同路径下。 37 | 38 | 接着,在控制台中输入启动Java项目指令: 39 | 40 | ``` 41 | java -jar MiniwWeChat.jar 42 | ``` 43 | 44 | 启动后相关的日志会保存在根路径的logs文件夹内 45 | 46 | ###架构 47 | 48 | ![](http://7xiwp6.com1.z0.glb.clouddn.com/服务器主体架构.png) 49 | 50 | [1]: https://github.com/MrNerverDie/MiniWeChat-Client 51 | -------------------------------------------------------------------------------- /src/server/PacketFromServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.IOException; 4 | 5 | import com.google.protobuf.Message.Builder; 6 | 7 | import tools.DataTypeTranslater; 8 | 9 | /** 10 | * 服务器要发给客户端的包 11 | * 12 | * @author Feng 13 | * 14 | */ 15 | public class PacketFromServer { 16 | private byte[] messageID = null; 17 | private int messageType = -1; 18 | private byte[] messageBoty = null; 19 | 20 | public PacketFromServer(int messageType, byte[] messageBoty) { 21 | setMessageID(ServerModel.createMessageId()); 22 | setMessageType(messageType); 23 | setMessageBoty(messageBoty); 24 | } 25 | 26 | public PacketFromServer(byte[] messageID, int messageType, byte[] messageBoty) { 27 | setMessageID(messageID); 28 | setMessageType(messageType); 29 | setMessageBoty(messageBoty); 30 | } 31 | 32 | public byte[] getMessageID() { 33 | return messageID; 34 | } 35 | 36 | public void setMessageID(byte[] messageID) { 37 | this.messageID = messageID; 38 | } 39 | 40 | public int getMessageType() { 41 | return messageType; 42 | } 43 | 44 | public byte[] getMessageTypeBytes() throws IOException { 45 | return DataTypeTranslater.intToByte(getMessageType()); 46 | } 47 | 48 | public void setMessageType(int messageType) { 49 | this.messageType = messageType; 50 | } 51 | 52 | public byte[] getMessageBoty() { 53 | return messageBoty; 54 | } 55 | 56 | public void setMessageBoty(byte[] messageBoty) { 57 | this.messageBoty = messageBoty; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/model/HibernateSessionFactory.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import org.hibernate.*; 4 | import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 5 | import org.hibernate.cfg.Configuration; 6 | import org.hibernate.service.ServiceRegistry; 7 | 8 | @SuppressWarnings("deprecation") 9 | public class HibernateSessionFactory { 10 | 11 | private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml"; 12 | private static final ThreadLocal threadLocal = new ThreadLocal(); 13 | private static Configuration configuration = new Configuration(); 14 | public static SessionFactory sessionFactory; 15 | private static String configFile = CONFIG_FILE_LOCATION; 16 | 17 | static { 18 | try{ 19 | configuration.configure(configFile); 20 | ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); 21 | sessionFactory = configuration.buildSessionFactory(sr); 22 | }catch(Exception e){ 23 | e.printStackTrace(); 24 | } 25 | 26 | 27 | } 28 | 29 | private HibernateSessionFactory() { 30 | 31 | } 32 | 33 | public static Session getSession() { 34 | Session session = threadLocal.get(); 35 | if (session == null || !session.isOpen()) { 36 | session = (sessionFactory != null) ? sessionFactory.openSession() : null; 37 | threadLocal.set(session); 38 | } 39 | return session; 40 | } 41 | 42 | /** 43 | * 提交Session 44 | * @param session 45 | * @author Feng 46 | */ 47 | public static void commitSession(Session session) { 48 | Transaction trans = session.beginTransaction(); 49 | trans.commit(); 50 | session.close(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/JUnit/TestGetGroupInfo.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | 7 | import model.Group; 8 | 9 | import org.junit.After; 10 | import org.junit.Test; 11 | 12 | import protocol.ProtoHead; 13 | import protocol.Msg.GetGroupInfoMsg.GetGroupInfoReq; 14 | import protocol.Msg.GetGroupInfoMsg.GetGroupInfoRsp; 15 | import server.NetworkPacket; 16 | 17 | /** 18 | * 测试获取群资料功能 19 | * 20 | * @author Administrator 21 | * 22 | */ 23 | public class TestGetGroupInfo { 24 | 25 | @After 26 | public void tearDown() throws Exception { 27 | } 28 | 29 | @Test 30 | public void test() throws IOException { 31 | String groupId = "13"; 32 | ClientSocket clientSocket = new ClientSocket(); 33 | 34 | GetGroupInfoReq.Builder requestBuilder = GetGroupInfoReq.newBuilder(); 35 | requestBuilder.setGroupId(groupId); 36 | 37 | clientSocket.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.GET_GROUP_INFO_REQ_VALUE, requestBuilder 38 | .build().toByteArray())); 39 | byte[] byteArray = clientSocket.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.GET_GROUP_INFO_RSP); 40 | GetGroupInfoRsp getGroupInfoRsp = GetGroupInfoRsp.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 41 | 42 | assertEquals(getGroupInfoRsp.getResultCode(), GetGroupInfoRsp.ResultCode.SUCCESS); 43 | assertEquals(getGroupInfoRsp.getGroupItem().getGroupId(), groupId); 44 | assertEquals(getGroupInfoRsp.getGroupItem().getCreaterUserId(), "a"); 45 | assertEquals(getGroupInfoRsp.getGroupItem().getGroupName(), "a,b,c,..."); 46 | System.out.println("Member Count : " + getGroupInfoRsp.getGroupItem().getMemberUserIdCount()); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/tools/GetImage.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.File; 5 | import java.net.HttpURLConnection; 6 | import java.net.URL; 7 | import javax.imageio.ImageIO; 8 | 9 | import org.apache.log4j.Logger; 10 | 11 | import server.ResourcePath; 12 | 13 | public class GetImage { 14 | static Logger logger = Logger.getLogger(GetImage.class); 15 | public static BufferedImage getImage(String imageName){ 16 | logger.info("GetImage.getImage:begin to get default image:"+imageName); 17 | BufferedImage image = null; 18 | try{ 19 | String urlStr=ResourcePath.getHeadDefaultPath()+imageName; 20 | logger.info("GetImage:imageUrl:"+urlStr); 21 | // URL url = new URL(urlStr); 22 | // HttpURLConnection connection2 = (HttpURLConnection) url.openConnection(); 23 | // String cookieVal=null; 24 | // String key=null; 25 | // String cookies=null; 26 | // for (int i = 1; (key = connection2.getHeaderFieldKey(i)) != null; i++ ) { 27 | // if (key.equalsIgnoreCase("set-cookie")) { 28 | // cookieVal = connection2.getHeaderField(i); 29 | // cookieVal = cookieVal.substring(0, cookieVal.indexOf(";")); 30 | // cookies = cookies+cookieVal+";"; 31 | // } 32 | // } 33 | // connection2.connect(); 34 | // image = ImageIO.read(connection2.getInputStream()); 35 | image = ImageIO.read(new File(urlStr)); 36 | logger.info("GetImage.getImage:get default image:"+imageName+" success!"); 37 | return image; 38 | }catch(Exception e){ 39 | logger.error("GetImage.getImage:get default image:"+imageName+" fail!"); 40 | logger.error(e.getStackTrace()); 41 | return null; 42 | } 43 | 44 | 45 | } 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | MiniWechat 7 | 8 | 9 | 22 | 23 | 24 | 25 | 26 | 27 | index.html 28 | index.htm 29 | index.jsp 30 | default.html 31 | default.htm 32 | default.jsp 33 | 34 | 35 | 36 | 37 | org.springframework.web.context.ContextLoaderListener 38 | 39 | 40 | contextConfigLocation 41 | /WEB-INF/classes/applicationContext.xml 42 | 43 | -------------------------------------------------------------------------------- /src/server/MinaDecoder.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | 5 | import org.apache.mina.core.buffer.IoBuffer; 6 | import org.apache.mina.core.session.IoSession; 7 | import org.apache.mina.filter.codec.CumulativeProtocolDecoder; 8 | import org.apache.mina.filter.codec.ProtocolDecoderOutput; 9 | 10 | import tools.DataTypeTranslater; 11 | 12 | /** 13 | * 接到客户端数据时的粘包方式 14 | * @author Feng 15 | * 16 | */ 17 | public class MinaDecoder extends CumulativeProtocolDecoder { 18 | private ByteArrayOutputStream byteArrayOutputStream; 19 | 20 | @Override 21 | protected boolean doDecode(IoSession ioSession, IoBuffer ioBuffer, ProtocolDecoderOutput output) throws Exception { 22 | // 如果没有接收完Size部分(4字节),直接返回false 23 | if (ioBuffer.remaining() < 4) 24 | return false; 25 | else { 26 | // 标记开始位置,如果一条消息没传输完成则返回到这个位置 27 | ioBuffer.mark(); 28 | 29 | byteArrayOutputStream = new ByteArrayOutputStream(); 30 | 31 | // 读取Size 32 | byte[] bytes = new byte[4]; 33 | ioBuffer.get(bytes); // 读取4字节的Size 34 | byteArrayOutputStream.write(bytes); 35 | int bodyLength = DataTypeTranslater.bytesToInt(bytes, 0) - DataTypeTranslater.INT_SIZE; // 按小字节序转int 36 | 37 | // 如果body没有接收完整,直接返回false 38 | if (ioBuffer.remaining() < bodyLength) { 39 | ioBuffer.reset(); // IoBuffer position回到原来标记的地方 40 | return false; 41 | } else { 42 | byte[] bodyBytes = new byte[bodyLength]; 43 | ioBuffer.get(bodyBytes); 44 | // String body = new String(bodyBytes, "UTF-8"); 45 | byteArrayOutputStream.write(bodyBytes); 46 | 47 | // 创建对象 48 | NetworkPacket packetFromClient = new NetworkPacket(ioSession, byteArrayOutputStream.toByteArray()); 49 | 50 | output.write(packetFromClient); // 解析出一条消息 51 | return true; 52 | } 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/server_HTTP/MyHttpServer.java: -------------------------------------------------------------------------------- 1 | package server_HTTP; 2 | 3 | public class MyHttpServer { 4 | } 5 | // 6 | // import java.io.IOException; 7 | // 8 | // import com.sun.net.httpserver.HttpExchange; 9 | // import com.sun.net.httpserver.HttpHandler; 10 | // import java.net.InetSocketAddress; 11 | // import java.util.HashMap; 12 | // import java.util.Map; 13 | // 14 | // import org.w3c.dom.Document; 15 | // 16 | // import com.sun.net.httpserver.HttpServer; 17 | // import com.sun.net.httpserver.spi.HttpServerProvider; 18 | // import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; 19 | // 20 | // public class MyHttpServer implements HttpHandler { 21 | // private Map contextMap = new HashMap(); 23 | // public String contextPath = ""; 24 | // 25 | // public static void main(String args[]) { 26 | // new MyHttpServer(); 27 | // } 28 | // 29 | // public MyHttpServer() { 30 | // try { 31 | // // 允许最大连接数 32 | // int backLog = 10; 33 | // InetSocketAddress inetSock = new InetSocketAddress(8086); 34 | // HttpServer httpServer = HttpServer.create(inetSock, backLog); 35 | // // 直接返回Hello..... 36 | // // httpServer.createContext("/", new HandlerTestA()); 37 | // // 显示已经处理的请求数,采用线程池 38 | // httpServer.createContext("/", this); 39 | // httpServer.setExecutor(null); 40 | // httpServer.start(); 41 | // System.out.println("HttpServer Test Start!"); 42 | // } catch (Exception e) { 43 | // e.printStackTrace(); 44 | // } 45 | // } 46 | // 47 | // @Override 48 | // public void handle(HttpExchange exchange) throws IOException { 49 | // System.out.println("fuck"); 50 | // System.out.println(exchange.getRequestURI()); 51 | // System.out.println(exchange.getRemoteAddress()); 52 | // System.out.println(exchange.getRequestBody().toString()); 53 | // System.out.println("shit"); 54 | // System.out.println(exchange.getRequestMethod()); 55 | // System.out.println(exchange.getRequestHeaders().size()); 56 | // } 57 | // } 58 | -------------------------------------------------------------------------------- /src/JUnit/TestDoubleLogin.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | import java.io.IOException; 5 | import java.net.UnknownHostException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import protocol.ProtoHead; 9 | import protocol.Msg.LoginMsg; 10 | import protocol.Msg.LoginMsg.LoginRsp.ResultCode; 11 | import server.NetworkPacket; 12 | 13 | import client.SocketClientTest; 14 | 15 | /** 16 | * 测试第二个人登陆后第一个人被踢下来的情况 17 | * 18 | * @author Feng 19 | * 20 | */ 21 | public class TestDoubleLogin { 22 | // public SocketClientTest client1, client2; 23 | 24 | // @Before 25 | // public void init() throws UnknownHostException, IOException { 26 | // client1 = new SocketClientTest(); 27 | // client1.link(); 28 | // client2 = new SocketClientTest(); 29 | // client2.link(); 30 | // } 31 | 32 | @Test 33 | public void test() throws UnknownHostException, IOException { 34 | ClientSocket client1, client2; 35 | String user = "a"; 36 | 37 | // 1号客户端登陆 38 | client1 = new ClientSocket(); 39 | ResultCode resultCode = client1.login(user, user); 40 | assertEquals(resultCode, LoginMsg.LoginRsp.ResultCode.SUCCESS); 41 | 42 | // 2号客户端登陆 43 | client2 = new ClientSocket(); 44 | resultCode = client2.login(user, user); 45 | assertEquals(resultCode, LoginMsg.LoginRsp.ResultCode.SUCCESS); 46 | 47 | // 检测1号客户端的收到的“踢下线”消息 48 | byte[] resultBytes; 49 | boolean getResponse = false; 50 | for (int i = 0; i < 2; i++) { 51 | resultBytes = client1.readFromServerWithoutKeepAlive(); 52 | // 其他消息,不管 53 | if (ProtoHead.ENetworkMessage.OFFLINE_SYNC != NetworkPacket.getMessageType(resultBytes)) 54 | continue; 55 | // System.err.println(NetworkMessage.getMessageType(resultBytes)); 56 | 57 | // 回复服务器 58 | // client1.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.OFFLINE_SYNC_VALUE, 59 | // NetworkPacket.getMessageID(resultBytes), new byte[]{})); 60 | 61 | // 踢人通知 62 | assertTrue(true); 63 | getResponse = true; 64 | return; 65 | } 66 | if (!getResponse) 67 | assertFalse(true); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/JUnit/TestAutoResponse.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | import java.net.UnknownHostException; 7 | 8 | import org.junit.Test; 9 | 10 | import protocol.ProtoHead; 11 | import protocol.Data.ChatData.ChatItem; 12 | import protocol.Msg.LoginMsg.LoginRsp; 13 | import protocol.Msg.ReceiveChatMsg.ReceiveChatSync; 14 | import protocol.Msg.SendChatMsg; 15 | import protocol.Msg.SendChatMsg.SendChatReq; 16 | import server.NetworkPacket; 17 | import test.Client111; 18 | 19 | /** 20 | * 测试自动回复器 21 | * 22 | * @author Feng 23 | * 24 | */ 25 | public class TestAutoResponse { 26 | 27 | @Test 28 | public void test() throws UnknownHostException, IOException { 29 | String user1 = "a", autoResponseUser = "AutoResponse", message = "Test AutoResponse!!!"; 30 | ClientSocket clientSocket1 = new ClientSocket(); 31 | 32 | // 登陆 33 | assertEquals(clientSocket1.login(user1, user1), LoginRsp.ResultCode.SUCCESS); 34 | System.out.println(user1 + " Login"); 35 | 36 | // 构造消息对象 37 | ChatItem.Builder sendChatItem = ChatItem.newBuilder(); 38 | sendChatItem.setSendUserId(user1); 39 | sendChatItem.setReceiveUserId(autoResponseUser); 40 | sendChatItem.setChatBody(message); 41 | sendChatItem.setChatType(ChatItem.ChatType.TEXT); 42 | 43 | SendChatReq.Builder sendChattingObj = SendChatReq.newBuilder(); 44 | sendChattingObj.setChatData(sendChatItem); 45 | 46 | // 发送 47 | clientSocket1.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.SEND_CHAT_REQ_VALUE, sendChattingObj 48 | .build().toByteArray())); 49 | System.out.println(user1 + " send Message to " + autoResponseUser + " : " + message); 50 | 51 | byte[] byteArray = clientSocket1.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 52 | assertNotNull(byteArray); 53 | ChatItem receiveChatItem = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)).getChatData(0); 54 | System.out.println(user1 + " get " + ClientSocket.getChatItemInfo(receiveChatItem)); 55 | assertEquals(receiveChatItem.getChatBody(), message); 56 | 57 | clientSocket1.close(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/createTable.sql: -------------------------------------------------------------------------------- 1 | #创建表chatting_message 2 | create table chatting_message (id bigint COMMENT '聊天消息Id' not null auto_increment, chatting_type int(8) COMMENT '聊天类型', group_id int(8) COMMENT '时间', is_group tinyint COMMENT '是否群聊', message char(100) COMMENT '消息', receiver_user_id char(20) COMMENT '接收者id', sender_user_id char(20) COMMENT '发送者id', time bigint(20) COMMENT '时间', primary key (id)); 3 | #创建表group_members 4 | create table group_members (group_id int(8) COMMENT '聊天群Id' not null, user_id char(20) COMMENT '微信号' not null); 5 | #创建表user 6 | create table user (user_id char(20) COMMENT '微信号' not null, user_headIndex int(4) not null default 0 COMMENT '头像编号', user_name char(20) not null COMMENT '昵称', user_password char(20) not null COMMENT '密码', primary key (user_id)); 7 | #创建表user——friends 8 | create table user_friends (user_id char(20) COMMENT '微信号' not null, friend_id char(20) COMMENT '微信号' not null); 9 | #创建表user_group 10 | create table user_group (group_id int(8) COMMENT '聊天群Id' not null auto_increment, group_name char(20) COMMENT '聊天群昵称',creater_id char(20) COMMENT '创建者微信号', primary key (group_id)); 11 | #新增联合主键 12 | alter table user_friends add primary key (user_id, friend_id); 13 | alter table group_members add primary key (user_id, group_id); 14 | #group_member新增外键 15 | alter table group_members add constraint fk_1 foreign key (user_id) references user (user_id); 16 | alter table group_members add constraint fk_2 foreign key (group_id) references user_group (group_id); 17 | #user_friends新增外键 18 | alter table user_friends add constraint fk_3 foreign key (friend_id) references user (user_id); 19 | alter table user_friends add constraint fk_4 foreign key (user_id) references user (user_id); 20 | #chatting_message新增外键 21 | alter table chatting_message add constraint fk_5 foreign key (receiver_user_id) references user (user_id); 22 | alter table chatting_message add constraint fk_6 foreign key (sender_user_id) references user (user_id); 23 | alter table chatting_message add constraint fk_7 foreign key (group_id) references user_group (group_id); 24 | #user_group新增外键 25 | alter table user_group add constraint fk_8 foreign key (creater_id) references user (user_id) ; -------------------------------------------------------------------------------- /src/JUnit/TestLogout.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.net.Socket; 8 | import java.net.UnknownHostException; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import protocol.Msg.LogoutMsg; 12 | import protocol.Msg.LoginMsg.LoginRsp; 13 | import protocol.Msg.LogoutMsg.LogoutRsp; 14 | import server.NetworkPacket; 15 | import client.SocketClientTest; 16 | 17 | public class TestLogout { 18 | private String user = "a"; 19 | // String host = "192.168.45.34"; // 要连接的服务端IP地址 20 | // int port = 8080; // 要连接的服务端对应的监听端口 21 | 22 | // public Socket socket; 23 | // public InputStream inputStream; 24 | // public OutputStream outputStream; 25 | // public SocketClientTest client; 26 | 27 | // @Before 28 | // public void init() throws UnknownHostException, IOException { 29 | // client = new SocketClientTest(); 30 | // client.link(); 31 | // } 32 | // 33 | // private void link() throws IOException { 34 | // socket = new Socket(host, port); 35 | // inputStream = socket.getInputStream(); 36 | // outputStream = socket.getOutputStream(); 37 | // } 38 | 39 | /** 40 | * 测试退出登录 41 | * 42 | * @throws IOException 43 | */ 44 | @Test 45 | public void testLogout() throws IOException { 46 | ClientSocket client = new ClientSocket(); 47 | 48 | LoginRsp.ResultCode resultCode = client.login(user, user); 49 | assertEquals(resultCode, LoginRsp.ResultCode.SUCCESS); 50 | // byte[] resultBytes = client.testLogout_JUnit(); 51 | // LogoutMsg.LogoutRsp responseObject = LogoutMsg.LogoutRsp.parseFrom(NetworkPacket.getMessageObjectBytes(resultBytes)); 52 | // assertEquals(responseObject.getResultCode().toString(), LogoutMsg.LogoutRsp.ResultCode.SUCCESS.toString()); 53 | 54 | LogoutRsp.ResultCode resultCode2 = client.logout(); 55 | assertEquals(resultCode2, LogoutRsp.ResultCode.SUCCESS); 56 | // resultBytes = client.testLogout_JUnit(); 57 | // responseObject = LogoutMsg.LogoutRsp.parseFrom(NetworkPacket.getMessageObjectBytes(resultBytes)); 58 | // assertEquals(responseObject.getResultCode().toString(), LogoutMsg.LogoutRsp.ResultCode.FAIL.toString()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/JUnit/TestGetUserInfo.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.fail; 5 | 6 | import java.io.IOException; 7 | import org.junit.Test; 8 | 9 | import protocol.ProtoHead; 10 | import protocol.Msg.GetUserInfoMsg; 11 | import protocol.Msg.GetUserInfoMsg.GetUserInfoRsp; 12 | import protocol.Msg.LoginMsg.LoginRsp; 13 | import server.NetworkPacket; 14 | 15 | /** 16 | * 对获取用户信息的测试 17 | * @author wangfei 18 | * 19 | */ 20 | public class TestGetUserInfo { 21 | /** 22 | * 测获取用户信息 23 | * @author wangfei 24 | * @throws IOException 25 | */ 26 | @Test 27 | public void testGetUserInfo() throws IOException{ 28 | String user1="a3",password1="aa",targetUserId="1"; 29 | 30 | System.out.println("TestGetPersonalInfo1:获取用户信息"); 31 | GetUserInfoRsp getUserInfoRsp1 = getResponse(user1,password1,targetUserId); 32 | System.out.println("服务器返回结果:"+getUserInfoRsp1.getResultCode().toString()); 33 | assertEquals(getUserInfoRsp1.getResultCode().getNumber(),GetUserInfoRsp.ResultCode.SUCCESS_VALUE); 34 | } 35 | 36 | 37 | 38 | private GetUserInfoRsp getResponse(String user,String password,String targetUserId) throws IOException { 39 | ClientSocket clientSocket = new ClientSocket(); 40 | byte[] response; 41 | // 登陆 42 | if (clientSocket.login(user, password) != LoginRsp.ResultCode.SUCCESS) 43 | fail("登陆结果错误!"); 44 | 45 | GetUserInfoMsg.GetUserInfoReq.Builder builder = GetUserInfoMsg.GetUserInfoReq.newBuilder(); 46 | builder.addTargetUserId(targetUserId); 47 | 48 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.GET_USERINFO_REQ.getNumber(), builder.build() 49 | .toByteArray()); 50 | //发消息 51 | clientSocket.writeToServer(byteArray); 52 | 53 | //接收回复 54 | while (true) { 55 | response = clientSocket.readFromServerWithoutKeepAlive(); 56 | ProtoHead.ENetworkMessage type = NetworkPacket.getMessageType(response); 57 | if(ProtoHead.ENetworkMessage.GET_USERINFO_RSP != type) 58 | continue; 59 | 60 | GetUserInfoRsp getUserInfoFriendRsp = GetUserInfoRsp.parseFrom(NetworkPacket.getMessageObjectBytes(response)); 61 | clientSocket.close(); 62 | return getUserInfoFriendRsp; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/model/Group.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.CascadeType; 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.JoinTable; 12 | import javax.persistence.JoinColumn; 13 | import javax.persistence.ManyToMany; 14 | import javax.persistence.Table; 15 | 16 | import org.hibernate.annotations.Cache; 17 | import org.hibernate.annotations.CacheConcurrencyStrategy; 18 | 19 | /** 20 | * 聊天群 21 | * 22 | * @author wangfei 23 | * @time 2015-04-02 24 | */ 25 | @Entity 26 | @Table(name = "user_group") 27 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 28 | public class Group { 29 | public static final String GROUP_ID = "groupId"; 30 | 31 | private int groupId; 32 | private String createrId; 33 | private String groupName; 34 | private List memberList; 35 | 36 | public Group() { 37 | } 38 | 39 | public Group(String groupName) { 40 | setGroupName(groupName); 41 | } 42 | 43 | @Id 44 | @Column(name = "group_id", columnDefinition = "int(8) COMMENT '聊天群Id'") 45 | @GeneratedValue(strategy = GenerationType.AUTO) 46 | public int getGroupId() { 47 | return groupId; 48 | } 49 | 50 | public void setGroupId(int groupId) { 51 | this.groupId = groupId; 52 | } 53 | 54 | @Column(name = "creater_id", columnDefinition = "char(20) COMMENT '微信号'") 55 | public String getCreaterId() { 56 | return createrId; 57 | } 58 | 59 | public void setCreaterId(String createrId) { 60 | this.createrId = createrId; 61 | } 62 | 63 | @Column(name = "group_name", columnDefinition = "char(20) COMMENT '聊天群昵称'") 64 | public String getGroupName() { 65 | return groupName; 66 | } 67 | 68 | public void setGroupName(String groupName) { 69 | this.groupName = groupName; 70 | } 71 | 72 | @ManyToMany(targetEntity = User.class, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) 73 | @JoinTable(name = "group_members", joinColumns = @JoinColumn(name = "group_id"), inverseJoinColumns = @JoinColumn(name = "user_id")) 74 | public List getMemberList() { 75 | return memberList; 76 | } 77 | 78 | public void setMemberList(List memberList) { 79 | this.memberList = memberList; 80 | } 81 | 82 | public String toString() { 83 | return "GroupId : " + this.groupId 84 | + "; GroupName : " + this.groupName 85 | + "; CreaterId : " + this.getCreaterId() 86 | + "; MemberList : " + this.getMemberList().toString(); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/JUnit/TestLogin.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | import java.io.IOException; 5 | import java.net.UnknownHostException; 6 | import org.junit.Before; 7 | import org.junit.Ignore; 8 | import org.junit.Test; 9 | import protocol.Msg.LoginMsg; 10 | import protocol.Msg.LogoutMsg; 11 | import protocol.Msg.LoginMsg.LoginRsp; 12 | import protocol.Msg.LogoutMsg.LogoutRsp; 13 | import client.SocketClientTest; 14 | import server.NetworkPacket; 15 | 16 | /** 17 | * 对登陆功能的测试(要先开服务器) 18 | * @author Feng 19 | * 20 | */ 21 | public class TestLogin { 22 | private String user = "a"; 23 | 24 | @Before 25 | public void init() throws UnknownHostException, IOException { 26 | // client.link(); 27 | } 28 | 29 | /** 30 | * 测试登陆功能 31 | * 测试账号错误,密码错误 32 | * @author Feng 33 | * @throws IOException 34 | * @throws UnknownHostException 35 | */ 36 | @Test 37 | // @Ignore 38 | public void testLogin() throws UnknownHostException, IOException { 39 | ClientSocket client = new ClientSocket(); 40 | String userId = "a"; 41 | 42 | System.out.println("Start Test1 Login!"); 43 | LoginRsp.ResultCode resultCode = client.login(userId, userId); 44 | assertEquals(resultCode, LoginMsg.LoginRsp.ResultCode.SUCCESS); 45 | 46 | resultCode = client.login(userId + "error", userId); 47 | assertEquals(resultCode, LoginMsg.LoginRsp.ResultCode.FAIL); 48 | 49 | resultCode = client.login(userId, userId + "error"); 50 | assertEquals(resultCode, LoginMsg.LoginRsp.ResultCode.FAIL); 51 | client.close(); 52 | } 53 | 54 | /** 55 | * 测试登陆,下线,登陆 56 | * @throws UnknownHostException 57 | * @throws IOException 58 | */ 59 | @Test 60 | @Ignore 61 | public void testLogin2() throws UnknownHostException, IOException { 62 | ClientSocket client = new ClientSocket(); 63 | 64 | String userId1 = "c", userId2 = "d"; 65 | System.out.println("Start Test2 Login!"); 66 | LoginRsp.ResultCode resultCode = client.login(userId1, userId1); 67 | assertEquals(LoginMsg.LoginRsp.ResultCode.SUCCESS, resultCode); 68 | 69 | // 下线 70 | LogoutRsp.ResultCode logoutResultCode = client.logout(); 71 | assertEquals(LogoutMsg.LogoutRsp.ResultCode.SUCCESS, logoutResultCode); 72 | 73 | // 再登录 74 | resultCode = client.login(userId2, userId2); 75 | assertEquals(LoginMsg.LoginRsp.ResultCode.SUCCESS, resultCode); 76 | 77 | // 下线 78 | logoutResultCode = client.logout(); 79 | assertEquals(LogoutRsp.ResultCode.SUCCESS, logoutResultCode); 80 | 81 | // 再登录 82 | resultCode = client.login(userId1, userId1); 83 | assertEquals(LoginMsg.LoginRsp.ResultCode.SUCCESS, resultCode); 84 | 85 | client.close(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/JUnit/TestDeleteFriend.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.fail; 5 | 6 | import java.io.IOException; 7 | import java.net.UnknownHostException; 8 | 9 | import org.junit.Test; 10 | 11 | import protocol.ProtoHead; 12 | import protocol.Msg.DeleteFriendMsg; 13 | import protocol.Msg.DeleteFriendMsg.DeleteFriendRsp; 14 | import protocol.Msg.LoginMsg.LoginRsp; 15 | import server.NetworkPacket; 16 | 17 | /** 18 | * 对删除好友的测试 19 | * @author wangfei 20 | * 21 | */ 22 | public class TestDeleteFriend { 23 | /** 24 | * 测试删除好友 25 | * @author wangfei 26 | * @throws IOException 27 | */ 28 | @Test 29 | public void testDeleteFriend() throws IOException{ 30 | System.out.println("TestDeleteFriend1:双方已经是好友关系删除好友"); 31 | String user1="a3",password1="aa",friend1="1"; 32 | DeleteFriendRsp deleteFriendRsp1 = getResponse(user1,password1,friend1); 33 | System.out.println("服务器返回结果:"+deleteFriendRsp1.getResultCode().toString()); 34 | assertEquals(deleteFriendRsp1.getResultCode().getNumber(), DeleteFriendRsp.ResultCode.SUCCESS_VALUE); 35 | 36 | System.out.println("TestDeleteFriend2:双方不是好友关系删除好友"); 37 | String user2="a",password2="a",friend2="2"; 38 | DeleteFriendRsp deleteFriendRsp2 = getResponse(user2,password2,friend2); 39 | System.out.println("服务器返回结果:"+deleteFriendRsp2.getResultCode().toString()); 40 | assertEquals(deleteFriendRsp2.getResultCode().getNumber(), DeleteFriendRsp.ResultCode.SUCCESS_VALUE); 41 | } 42 | 43 | private DeleteFriendRsp getResponse(String user,String password,String friend) throws UnknownHostException, IOException{ 44 | ClientSocket clientSocket = new ClientSocket(); 45 | byte[] response; 46 | // 登陆 47 | if (clientSocket.login(user, password) != LoginRsp.ResultCode.SUCCESS) 48 | fail("登陆结果错误!"); 49 | 50 | DeleteFriendMsg.DeleteFriendReq.Builder builder = DeleteFriendMsg.DeleteFriendReq.newBuilder(); 51 | builder.setFriendUserId(friend); 52 | 53 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.DELETE_FRIEND_REQ.getNumber(), builder.build() 54 | .toByteArray()); 55 | //发消息 56 | clientSocket.writeToServer(byteArray); 57 | 58 | //接收回复 59 | while (true) { 60 | response = clientSocket.readFromServerWithoutKeepAlive(); 61 | ProtoHead.ENetworkMessage type = NetworkPacket.getMessageType(response); 62 | if(ProtoHead.ENetworkMessage.DELETE_FRIEND_RSP != type) 63 | continue; 64 | 65 | DeleteFriendRsp deleteFriendRsp = DeleteFriendRsp.parseFrom(NetworkPacket.getMessageObjectBytes(response)); 66 | clientSocket.close(); 67 | return deleteFriendRsp; 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/ConnectionPoolTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | import protocol.ProtoHead; 9 | import protocol.Msg.LoginMsg; 10 | import protocol.Msg.LoginMsg.LoginRsp; 11 | import server.NetworkPacket; 12 | import tools.DataTypeTranslater; 13 | 14 | 15 | public class ConnectionPoolTest { 16 | Socket socket; 17 | InputStream inputStream; 18 | OutputStream outputStream; 19 | private static String host = "127.0.0.1"; 20 | private static int port = 8081; 21 | 22 | public static void main(String args[]){ 23 | //测试多用户同时在线的情况时 连接池是否正常 24 | ConnectionPoolTest t = new ConnectionPoolTest(); 25 | t.login("11", "1"); 26 | // t.login("2", "1"); 27 | // t.login("3", "1"); 28 | // t.login("4", "1"); 29 | // t.login("5", "1"); 30 | // t.login("6", "1"); 31 | // t.login("7", "1"); 32 | // t.login("8", "1"); 33 | // t.login("9", "1"); 34 | // t.login("10", "1"); 35 | // t.login("11", "1"); 36 | } 37 | private void login(String user,String password){ 38 | 39 | 40 | LoginMsg.LoginReq.Builder builder = LoginMsg.LoginReq.newBuilder(); 41 | builder.setUserId(user); 42 | builder.setUserPassword(password); 43 | try { 44 | socket = new Socket(host, port); 45 | inputStream = socket.getInputStream(); 46 | outputStream = socket.getOutputStream(); 47 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.LOGIN_REQ.getNumber(), builder.build().toByteArray()); 48 | writeToServer(byteArray); 49 | while (true) { 50 | byteArray = readFromServer(); 51 | ProtoHead.ENetworkMessage type = NetworkPacket.getMessageType(byteArray); 52 | if(ProtoHead.ENetworkMessage.LOGIN_RSP == type){ 53 | LoginRsp loginRsp = LoginRsp.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 54 | System.out.println(user+":登录结果:"+loginRsp.getResultCode().toString()); 55 | } 56 | else{ 57 | System.out.println(type); 58 | } 59 | } 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | 64 | } 65 | public void writeToServer(byte[] arrayBytes) throws IOException { 66 | // outputStream = socket.getOutputStream(); 67 | outputStream.write(arrayBytes); 68 | // outputStream.close(); 69 | } 70 | 71 | public byte[] readFromServer() throws IOException { 72 | byte[] byteArray = new byte[200]; 73 | inputStream.read(byteArray); 74 | byteArray = cutResult(byteArray); 75 | return byteArray; 76 | } 77 | 78 | public byte[] cutResult(byte[] byteArray) { 79 | int size = DataTypeTranslater.bytesToInt(byteArray, 0); 80 | byte[] result = new byte[size]; 81 | for (int i = 0; i < size; i++) 82 | result[i] = byteArray[i]; 83 | return result; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/tools/DataTypeTranslater.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | import java.nio.ByteBuffer; 9 | import java.util.Calendar; 10 | 11 | // 数据转换器 12 | public class DataTypeTranslater { 13 | public static final int INT_SIZE = 4; 14 | 15 | /** 16 | * int转byte[] 17 | * @param number 18 | * @return 19 | * @throws IOException 20 | */ 21 | public static byte[] intToByte(int number) throws IOException { 22 | ByteArrayOutputStream boutput = new ByteArrayOutputStream(); 23 | DataOutputStream doutput = new DataOutputStream(boutput); 24 | doutput.writeInt(number); 25 | return boutput.toByteArray(); 26 | } 27 | 28 | /** 29 | * byte[4] 转int 30 | * @param bytes 31 | * @param offset 32 | * @return 33 | */ 34 | public static int bytesToInt(byte[] bytes, int offset) { 35 | int value= 0; 36 | for (int i = 0; i < 4; i++) { 37 | int shift= (4 - 1 - i) * 8; 38 | value +=(bytes[i + offset] & 0x000000FF) << shift; 39 | } 40 | return value; 41 | } 42 | 43 | private static ByteBuffer bbuf; 44 | /** 45 | * float 转 byte[4] 46 | * @param number 47 | * @return 48 | */ 49 | public static byte[] floatToBytes(float number) { 50 | bbuf = ByteBuffer.allocate(4); 51 | bbuf.putFloat(number); 52 | return bbuf.array(); 53 | } 54 | 55 | /** 56 | * 文件转Byte[] 57 | * @param address 58 | * @return 59 | * @throws IOException 60 | */ 61 | public static byte[] fileToByte(String address) throws IOException { 62 | // System.err.println("FilePath : " + address); 63 | 64 | File file = new File(address); 65 | long fileSize = file.length(); 66 | 67 | FileInputStream fi = new FileInputStream(file); 68 | byte[] buffer = new byte[(int) fileSize]; 69 | 70 | int offset = 0; 71 | int numRead = 0; 72 | while (offset < buffer.length && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) { 73 | offset += numRead; 74 | } 75 | // 获取字节数组长度 76 | if (offset != buffer.length) { 77 | throw new IOException("Could not completely read file " + file.getName()); 78 | } 79 | fi.close(); 80 | return buffer; 81 | } 82 | 83 | /** 84 | * 日期输出 85 | * @param time 86 | * @return 87 | * @author Feng 88 | */ 89 | public static String getData(long time) { 90 | Calendar calendar = Calendar.getInstance(); 91 | calendar.setTimeInMillis(time); 92 | String t = calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONDAY) + "-" + calendar.get(Calendar.DAY_OF_MONTH) 93 | + " " + calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE) + ":" 94 | + calendar.get(Calendar.SECOND); 95 | 96 | return t; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/tools/Debug.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.util.Date; 4 | import org.apache.log4j.Logger; 5 | 6 | public class Debug { 7 | public static enum LogType{NO, ERROR, FAULT, EXCEPTION}; 8 | public static final int ERROR=0, Fault=1, Exception=2; 9 | 10 | public static boolean LogSwitch = false; 11 | public static boolean LoggerSwitch = true; 12 | static Logger logger = Logger.getLogger(Debug.class); 13 | 14 | public static void init(){ 15 | if(logger == null){ 16 | logger = Logger.getLogger(Debug.class); 17 | } 18 | } 19 | 20 | public static void log(String messsage) { 21 | log(LogType.NO, messsage); 22 | } 23 | 24 | public static void log(LogType logType, String messsage) { 25 | init(); 26 | if (LogSwitch) { 27 | System.out.print(getTime()); 28 | if (logType != LogType.NO) 29 | System.out.print(getLogTypeString(logType)); 30 | System.out.println(messsage); 31 | } 32 | 33 | if (LoggerSwitch) 34 | if (logType != LogType.NO) 35 | logger.info(getLogTypeString(logType) + messsage); 36 | else 37 | logger.info(messsage); 38 | } 39 | 40 | 41 | public static void log(String head, String messsage) { 42 | log(LogType.NO, head, messsage); 43 | } 44 | 45 | public static void log(LogType logType, String head, String messsage) { 46 | init(); 47 | if (LogSwitch) { 48 | System.out.print(getTime()); 49 | if (logType != LogType.NO) 50 | System.out.print(getLogTypeString(logType)); 51 | 52 | System.out.println(head + " : " + messsage); 53 | } 54 | 55 | if (LoggerSwitch) 56 | if (logType != LogType.NO) 57 | logger.info(getLogTypeString(logType) + head + " : " + messsage); 58 | else 59 | logger.info(head + " : " + messsage); 60 | } 61 | 62 | public static void log(String[] heads, String messsage) { 63 | log(LogType.NO, heads, messsage); 64 | } 65 | 66 | public static void log(LogType logType, String[] heads, String messsage) { 67 | init(); 68 | if (LogSwitch) { 69 | System.out.print(getTime()); 70 | 71 | if (logType != LogType.NO) 72 | System.out.print(getLogTypeString(logType)); 73 | 74 | for (String s : heads) 75 | System.out.print(s + " : "); 76 | 77 | System.out.println(messsage); 78 | } 79 | 80 | if (LoggerSwitch) { 81 | logger.info(getTime()); 82 | 83 | String str = getLogTypeString(logType); 84 | 85 | for (String s : heads) 86 | str += s + " : "; 87 | 88 | str += messsage; 89 | 90 | logger.info(str); 91 | } 92 | 93 | } 94 | 95 | public static String getTime(){ 96 | Date date = new Date(); 97 | return "[" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "]"; 98 | } 99 | 100 | private static String getLogTypeString(LogType logType){ 101 | return "[" + logType.toString() + "]"; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/tools/AutoResponseClient.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.net.UnknownHostException; 8 | 9 | import org.apache.log4j.Logger; 10 | 11 | import protocol.ProtoHead; 12 | import protocol.Data.ChatData.ChatItem; 13 | import protocol.Data.ChatData.ChatItem.TargetType; 14 | import protocol.Msg.LoginMsg.LoginRsp; 15 | import protocol.Msg.ReceiveChatMsg.ReceiveChatSync; 16 | import protocol.Msg.SendChatMsg.SendChatReq; 17 | import server.NetworkPacket; 18 | 19 | import JUnit.ClientSocket; 20 | 21 | /** 22 | * 一个自动回复其他用户发来消息的插件 23 | * 24 | * @author Feng 25 | * 26 | */ 27 | public class AutoResponseClient { 28 | private ClientSocket clientSocket; 29 | private Logger logger = Logger.getLogger(this.getClass()); 30 | 31 | public AutoResponseClient() throws UnknownHostException, IOException { 32 | String user = "AutoResponse"; 33 | clientSocket = new ClientSocket(); 34 | clientSocket.host = "127.0.0.1"; 35 | // clientSocket.link(); 36 | if (clientSocket.login(user, user) != LoginRsp.ResultCode.SUCCESS) { 37 | // Debug.log("AutoResponseClient", "自动回复器登陆失败!"); 38 | logger.error("AutoResponseClient : AutoResponse Login Error!"); 39 | // System.err.println("AutoResponseClient : 自动回复器登陆失败!"); 40 | return; 41 | } 42 | logger.info("AutoResponse Login Successful! Start working"); 43 | 44 | byte[] arrayBytes; 45 | while (true) { 46 | arrayBytes = clientSocket.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 47 | // if (NetworkPacket.getMessageType(arrayBytes) != ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC) 48 | // continue; 49 | 50 | // 将同样的消息发回给发送者 51 | ReceiveChatSync receiveChatting = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(arrayBytes)); 52 | ChatItem receiveChatItem = receiveChatting.getChatData(0); 53 | logger.info("AutoResponse get a Chatting : " + ClientSocket.getChatItemInfo(receiveChatItem)); 54 | 55 | ChatItem.Builder sendChatItem = ChatItem.newBuilder(); 56 | if (receiveChatItem.getTargetType() == TargetType.INDIVIDUAL){ 57 | sendChatItem.setSendUserId(receiveChatItem.getReceiveUserId()); 58 | sendChatItem.setReceiveUserId(receiveChatItem.getSendUserId()); 59 | } else if (receiveChatItem.getTargetType() == TargetType.GROUP){ 60 | sendChatItem.setSendUserId(user); 61 | } 62 | sendChatItem.setChatBody(receiveChatItem.getChatBody()); 63 | sendChatItem.setChatType(receiveChatItem.getChatType()); 64 | 65 | SendChatReq.Builder sendChattingObj = SendChatReq.newBuilder(); 66 | sendChattingObj.setChatData(sendChatItem); 67 | 68 | clientSocket.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.SEND_CHAT_REQ_VALUE, sendChattingObj 69 | .build().toByteArray())); 70 | logger.info("AutoResponse response a Chatting"); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/JUnit/TestAddFriend.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.fail; 5 | 6 | import java.io.IOException; 7 | import java.net.UnknownHostException; 8 | import org.junit.Test; 9 | 10 | import protocol.ProtoHead; 11 | import protocol.Msg.AddFriendMsg; 12 | import protocol.Msg.AddFriendMsg.AddFriendRsp; 13 | import protocol.Msg.LoginMsg.LoginRsp; 14 | import server.NetworkPacket; 15 | 16 | /** 17 | * 对添加好友的测试 18 | * @author wangfei 19 | * 20 | */ 21 | public class TestAddFriend { 22 | /** 23 | * 测试添加好友 24 | * @author wangfei 25 | * @throws IOException 26 | */ 27 | @Test 28 | public void testAddFriend() throws IOException{ 29 | System.out.println("TestAddFriend1:双方不是好友关系添加好友"); 30 | String user1="a3",password1="aa",friend1="a"; 31 | AddFriendRsp addFriendRsp1 = getResponse(user1,password1,friend1); 32 | System.out.println("服务器返回结果:"+addFriendRsp1.getResultCode().toString()); 33 | assertEquals(addFriendRsp1.getResultCode().getNumber(), AddFriendRsp.ResultCode.SUCCESS_VALUE); 34 | 35 | System.out.println("TestAddFriend2:双方已经是好友关系继续添加好友"); 36 | String user2="a",password2="a",friend2="newuser1"; 37 | AddFriendRsp addFriendRsp2 = getResponse(user2,password2,friend2); 38 | System.out.println("服务器返回结果:"+addFriendRsp2.getResultCode().toString()); 39 | assertEquals(addFriendRsp2.getResultCode().getNumber(), AddFriendRsp.ResultCode.SUCCESS_VALUE); 40 | 41 | System.out.println("TestAddFriend3:添加不存在的用户为好友"); 42 | String user3="newuser1",password3="123",friend3="ttttttt"; 43 | AddFriendRsp addFriendRsp3 = getResponse(user3,password3,friend3); 44 | System.out.println("服务器返回结果:"+addFriendRsp3.getResultCode().toString()); 45 | assertEquals(addFriendRsp3.getResultCode().getNumber(), AddFriendRsp.ResultCode.FAIL_VALUE); 46 | 47 | } 48 | 49 | private AddFriendRsp getResponse(String user,String password,String friend) throws UnknownHostException, IOException{ 50 | ClientSocket clientSocket = new ClientSocket(); 51 | byte[] response; 52 | // 登陆 53 | if (clientSocket.login(user, password) != LoginRsp.ResultCode.SUCCESS) 54 | fail("登陆结果错误!"); 55 | 56 | AddFriendMsg.AddFriendReq.Builder builder = AddFriendMsg.AddFriendReq.newBuilder(); 57 | builder.setFriendUserId(friend); 58 | 59 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.ADD_FRIEND_REQ.getNumber(), builder.build() 60 | .toByteArray()); 61 | //发消息 62 | clientSocket.writeToServer(byteArray); 63 | 64 | //接收回复 65 | while (true) { 66 | response = clientSocket.readFromServerWithoutKeepAlive(); 67 | ProtoHead.ENetworkMessage type = NetworkPacket.getMessageType(response); 68 | if(ProtoHead.ENetworkMessage.ADD_FRIEND_RSP != type) 69 | continue; 70 | 71 | AddFriendRsp addFriendRsp = AddFriendRsp.parseFrom(NetworkPacket.getMessageObjectBytes(response)); 72 | clientSocket.close(); 73 | return addFriendRsp; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/hibernate.cfg.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | com.mysql.jdbc.Driver 12 | jdbc:mysql://127.0.0.1:3306/MiniWechat?useUnicode=true&characterEncoding=UTF-8 13 | root 14 | root 15 | 16 | none 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.hibernate.dialect.MySQLDialect 24 | 25 | 26 | thread 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 1 37 | 100 38 | 5 39 | 0 40 | 2 41 | 90 42 | SELECT CURRENT_USER 43 | 18000 44 | 25000 45 | true 46 | 47 | 48 | 49 | 50 | true 51 | 52 | 53 | 54 | 55 | 56 | org.hibernate.cache.ehcache.EhCacheRegionFactory 57 | true 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/JUnit/TestRegister.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.net.Socket; 8 | import java.net.UnknownHostException; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | 12 | import protocol.ProtoHead; 13 | import protocol.Msg.RegisterMsg; 14 | import protocol.Msg.PersonalSettingsMsg.PersonalSettingsRsp; 15 | import protocol.Msg.RegisterMsg.RegisterRsp; 16 | import server.NetworkPacket; 17 | 18 | import client.SocketClientTest; 19 | 20 | /** 21 | * 对注册功能的测试(要先开服务器) 22 | * @author Feng 23 | * 24 | */ 25 | public class TestRegister { 26 | // String host = "192.168.45.11"; // 要连接的服务端IP地址 27 | // String host = "192.168.45.34"; // 要连接的服务端IP地址 28 | // int port = 8080; // 要连接的服务端对应的监听端口 29 | // 30 | // public Socket socket; 31 | // public InputStream inputStream; 32 | // public OutputStream outputStream; 33 | // public SocketClientTest client; 34 | // 35 | // @Before 36 | // public void init() throws UnknownHostException, IOException { 37 | // client = new SocketClientTest(); 38 | // client.link(); 39 | // } 40 | // 41 | // private void link() throws IOException { 42 | // socket = new Socket(host, port); 43 | // inputStream = socket.getInputStream(); 44 | // outputStream = socket.getOutputStream(); 45 | // } 46 | 47 | 48 | /** 49 | * 测试注册功能(由JUnit调用) 50 | * 51 | * @author Feng 52 | * @return 53 | * @throws IOException 54 | */ 55 | private RegisterRsp.ResultCode testRegister_JUint(ClientSocket client, String userId, String userPassword, String userName) throws IOException { 56 | RegisterMsg.RegisterReq.Builder builder = RegisterMsg.RegisterReq.newBuilder(); 57 | builder.setUserId(userId); 58 | builder.setUserPassword(userPassword); 59 | builder.setUserName(userName); 60 | 61 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.REGISTER_REQ.getNumber(), builder.build() 62 | .toByteArray()); 63 | client.writeToServer(byteArray); 64 | 65 | for (int i=0; i<10; i++) { 66 | byteArray = client.readFromServerWithoutKeepAlive(); 67 | System.out.println(NetworkPacket.getMessageType(byteArray).toString()); 68 | if (NetworkPacket.getMessageType(byteArray) != ProtoHead.ENetworkMessage.REGISTER_RSP) 69 | continue; 70 | 71 | return RegisterRsp.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)).getResultCode(); 72 | } 73 | return RegisterRsp.ResultCode.USER_EXIST; 74 | } 75 | 76 | /** 77 | * 测试注册功能 78 | * 79 | * @author Feng 80 | * @throws IOException 81 | */ 82 | @Test 83 | public void testRegister() throws IOException { 84 | ClientSocket client = new ClientSocket(); 85 | 86 | // String randomData = (((int) (Math.random() * 100000)) + "").substring(0, 5); 87 | String randomData = "AutoResponse"; 88 | RegisterRsp.ResultCode resultCode = testRegister_JUint(client, randomData, randomData, randomData); 89 | assertEquals(RegisterMsg.RegisterRsp.ResultCode.SUCCESS, resultCode); 90 | 91 | resultCode = testRegister_JUint(client, randomData, randomData, randomData); 92 | assertEquals(RegisterMsg.RegisterRsp.ResultCode.USER_EXIST, resultCode); 93 | 94 | client.close(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/JUnit/TestGetPersonalInfo.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.fail; 5 | 6 | import java.io.IOException; 7 | import java.net.UnknownHostException; 8 | 9 | import org.junit.Test; 10 | 11 | import protocol.ProtoHead; 12 | import protocol.Msg.GetPersonalInfoMsg; 13 | import protocol.Msg.GetPersonalInfoMsg.GetPersonalInfoRsp; 14 | import protocol.Msg.LoginMsg.LoginRsp; 15 | import server.NetworkPacket; 16 | 17 | 18 | 19 | public class TestGetPersonalInfo { 20 | /** 21 | * 测获取个人信息 22 | * @throws IOException 23 | * @author wangfei 24 | * @time 2015-03-26 25 | */ 26 | @Test 27 | public void testGetPersonalInfo() throws IOException{ 28 | String user1="3",password1="1"; 29 | System.out.println("TestGetPersonalInfo1:只获取个人信息"); 30 | GetPersonalInfoRsp getPersonalInfoRsp1 = getResponse(user1,password1,true,false,false); 31 | System.out.println("服务器返回结果:"+getPersonalInfoRsp1.getResultCode().toString()); 32 | assertEquals(getPersonalInfoRsp1.getResultCode().getNumber(),GetPersonalInfoRsp.ResultCode.SUCCESS_VALUE); 33 | 34 | String user2="1",password2="1"; 35 | System.out.println("TestGetPersonalInfo2:获取个人信息、好友信息"); 36 | GetPersonalInfoRsp getPersonalInfoRsp2 = getResponse(user2,password2,true,true,false); 37 | System.out.println("服务器返回结果:"+getPersonalInfoRsp2.getResultCode().toString()); 38 | assertEquals(getPersonalInfoRsp2.getResultCode().getNumber(),GetPersonalInfoRsp.ResultCode.SUCCESS_VALUE); 39 | 40 | String user3="a3",password3="aa"; 41 | System.out.println("TestGetPersonalInfo3:获取个人信息、好友信息、群聊信息"); 42 | GetPersonalInfoRsp getPersonalInfoRsp3 = getResponse(user3,password3,true,true,true); 43 | System.out.println("服务器返回结果:"+getPersonalInfoRsp3.getResultCode().toString()); 44 | assertEquals(getPersonalInfoRsp3.getResultCode().getNumber(),GetPersonalInfoRsp.ResultCode.SUCCESS_VALUE); 45 | 46 | } 47 | 48 | private GetPersonalInfoRsp getResponse(String user,String password,boolean userInfo,boolean friendInfo,boolean groupInfo) throws UnknownHostException, IOException{ 49 | ClientSocket clientSocket = new ClientSocket(); 50 | byte[] response; 51 | // 登陆 52 | if (clientSocket.login(user, password) != LoginRsp.ResultCode.SUCCESS) 53 | fail("登陆结果错误!"); 54 | GetPersonalInfoMsg.GetPersonalInfoReq.Builder builder = GetPersonalInfoMsg.GetPersonalInfoReq.newBuilder(); 55 | builder.setUserInfo(userInfo); 56 | builder.setFriendInfo(friendInfo); 57 | builder.setGroupInfo(groupInfo); 58 | 59 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.GET_PERSONALINFO_REQ.getNumber(), builder.build() 60 | .toByteArray()); 61 | //发消息 62 | clientSocket.writeToServer(byteArray); 63 | 64 | //接收回复 65 | while (true) { 66 | response = clientSocket.readFromServerWithoutKeepAlive(); 67 | ProtoHead.ENetworkMessage type = NetworkPacket.getMessageType(response); 68 | if(ProtoHead.ENetworkMessage.GET_PERSONALINFO_RSP != type) 69 | continue; 70 | 71 | GetPersonalInfoRsp getPersonalInfoFriendRsp = GetPersonalInfoRsp.parseFrom(NetworkPacket.getMessageObjectBytes(response)); 72 | clientSocket.close(); 73 | return getPersonalInfoFriendRsp; 74 | } 75 | 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/JUnit/TestPersonalSettings.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.fail; 5 | 6 | import java.io.IOException; 7 | import org.junit.Test; 8 | 9 | import protocol.ProtoHead; 10 | import protocol.Msg.PersonalSettingsMsg; 11 | import protocol.Msg.LoginMsg.LoginRsp; 12 | import protocol.Msg.PersonalSettingsMsg.PersonalSettingsRsp; 13 | import server.NetworkPacket; 14 | 15 | 16 | /** 17 | * 对个人设置功能的测试 18 | * 19 | * @author wangfei 20 | * 21 | */ 22 | public class TestPersonalSettings { 23 | /** 24 | * 测试个人设置 25 | * 26 | * @author wangfei 27 | * @throws IOException 28 | */ 29 | @Test 30 | public void testPersonalSettings() throws IOException { 31 | String user1="1",password1="1"; 32 | System.out.println("TestPersonalSettings1:只设置昵称"); 33 | PersonalSettingsRsp personalSettingsRsp1 = getResponse(user1,password1,"newname-test1",null,0); 34 | System.out.println("服务器返回结果:"+personalSettingsRsp1.getResultCode().toString()); 35 | assertEquals(personalSettingsRsp1.getResultCode().getNumber(),PersonalSettingsRsp.ResultCode.SUCCESS_VALUE); 36 | 37 | String user2="2",password2="1"; 38 | System.out.println("TestPersonalSettings2:只设置密码"); 39 | PersonalSettingsRsp personalSettingsRsp2 = getResponse(user2,password2,null,"newpassword-test2",0); 40 | System.out.println("服务器返回结果:"+personalSettingsRsp2.getResultCode().toString()); 41 | assertEquals(personalSettingsRsp2.getResultCode().getNumber(),PersonalSettingsRsp.ResultCode.SUCCESS_VALUE); 42 | 43 | String user3="3",password3="1"; 44 | System.out.println("TestPersonalSettings3:只设置头像"); 45 | PersonalSettingsRsp personalSettingsRsp3 = getResponse(user3,password3,null,null,1); 46 | System.out.println("服务器返回结果:"+personalSettingsRsp3.getResultCode().toString()); 47 | assertEquals(personalSettingsRsp3.getResultCode().getNumber(),PersonalSettingsRsp.ResultCode.SUCCESS_VALUE); 48 | } 49 | 50 | private PersonalSettingsRsp getResponse(String user,String password,String newUserName,String newPassword,int newHeadInx) throws IOException{ 51 | ClientSocket clientSocket = new ClientSocket(); 52 | byte[] response; 53 | // 登陆 54 | if (clientSocket.login(user, password) != LoginRsp.ResultCode.SUCCESS) 55 | fail("登陆结果错误!"); 56 | 57 | PersonalSettingsMsg.PersonalSettingsReq.Builder builder = PersonalSettingsMsg.PersonalSettingsReq.newBuilder(); 58 | if(newUserName != null) 59 | builder.setUserName(newUserName); 60 | if(newPassword != null) 61 | builder.setUserPassword(newPassword); 62 | if(newHeadInx != 0) 63 | builder.setHeadIndex(newHeadInx); 64 | 65 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.PERSONALSETTINGS_REQ.getNumber(), builder.build() 66 | .toByteArray()); 67 | //发消息 68 | clientSocket.writeToServer(byteArray); 69 | 70 | //接收回复 71 | while (true) { 72 | response = clientSocket.readFromServerWithoutKeepAlive(); 73 | ProtoHead.ENetworkMessage type = NetworkPacket.getMessageType(response); 74 | if(ProtoHead.ENetworkMessage.PERSONALSETTINGS_RSP != type) 75 | continue; 76 | 77 | PersonalSettingsRsp personalSettingsRsp = PersonalSettingsRsp.parseFrom(NetworkPacket.getMessageObjectBytes(response)); 78 | clientSocket.close(); 79 | return personalSettingsRsp; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /.classpath.orig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | <<<<<<< HEAD 35 | 36 | ======= 37 | 38 | >>>>>>> ·【功能优化】取消Tomcat 1.2 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/server/MinaEncoder.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | 6 | import org.apache.log4j.Logger; 7 | import org.apache.mina.core.buffer.IoBuffer; 8 | import org.apache.mina.core.session.IoSession; 9 | import org.apache.mina.filter.codec.ProtocolEncoderAdapter; 10 | import org.apache.mina.filter.codec.ProtocolEncoderOutput; 11 | 12 | import exception.NoIpException; 13 | 14 | import tools.DataTypeTranslater; 15 | 16 | /** 17 | * 向客户端发数据时的组成模式 18 | * 19 | * @author Feng 20 | * 21 | */ 22 | public class MinaEncoder extends ProtocolEncoderAdapter { 23 | Logger logger = Logger.getLogger(this.getClass()); 24 | private ByteArrayOutputStream byteArrayOutputStream; 25 | private PacketFromServer packetWillSend; 26 | 27 | @Override 28 | public void encode(IoSession ioSession, Object message, ProtocolEncoderOutput output) throws Exception { 29 | // String msg = (String) message; 30 | // byte[] bytes = msg.getBytes("UTF-8"); 31 | 32 | byteArrayOutputStream = new ByteArrayOutputStream(); 33 | byte[] byteArray; 34 | if (message.getClass().equals(PacketFromServer.class)) { 35 | packetWillSend = (PacketFromServer) message; 36 | 37 | // 1.加入类型 38 | byteArrayOutputStream.write(packetWillSend.getMessageTypeBytes()); 39 | 40 | // 2.添加MessageId 41 | byteArrayOutputStream.write(packetWillSend.getMessageID()); 42 | 43 | // 3.加入数据包 44 | byteArrayOutputStream.write(packetWillSend.getMessageBoty()); 45 | 46 | int sizeOfAll = byteArrayOutputStream.size() + DataTypeTranslater.INT_SIZE; 47 | byteArray = byteArrayOutputStream.toByteArray(); 48 | 49 | IoBuffer buffer = IoBuffer.allocate(sizeOfAll); 50 | buffer.put(DataTypeTranslater.intToByte(sizeOfAll)); // header 51 | buffer.put(byteArray); // body 52 | buffer.flip(); 53 | output.write(buffer); 54 | 55 | // showPacket(ioSession, sizeOfAll, byteArray); 56 | return; 57 | } 58 | 59 | byte[] bytes = (byte[]) message; 60 | int length = bytes.length; 61 | // System.out.println("MinaEncoder : " + length); 62 | byte[] header = DataTypeTranslater.intToByte(length); // 按小字节序转成字节数组 63 | 64 | IoBuffer buffer = IoBuffer.allocate(length + DataTypeTranslater.INT_SIZE); 65 | buffer.put(header); // header 66 | buffer.put(bytes); // body 67 | buffer.flip(); 68 | output.write(buffer); 69 | } 70 | 71 | private ByteArrayOutputStream byteArrayOutputStream2; 72 | 73 | private void showPacket(IoSession ioSession, int size, byte[] byteArray) { 74 | byteArrayOutputStream2 = new ByteArrayOutputStream(); 75 | try { 76 | byteArrayOutputStream2.write(DataTypeTranslater.intToByte(size)); 77 | byteArrayOutputStream2.write(byteArray); 78 | byte[] newByteArray = byteArrayOutputStream2.toByteArray(); 79 | try { 80 | logger.info("111111111111111111111111111111111111111111111111"); 81 | logger.info("Server send Message to Client(" + ServerModel.getIoSessionKey(ioSession).toString() + ") ,Type : " 82 | + NetworkPacket.getMessageType(newByteArray) + " MessageId : " 83 | + DataTypeTranslater.bytesToInt(NetworkPacket.getMessageID(newByteArray), 0)); 84 | } catch (NoIpException e) { 85 | e.printStackTrace(); 86 | } 87 | } catch (IOException e) { 88 | e.printStackTrace(); 89 | } 90 | NetworkPacket.showPacket(logger, ioSession, byteArrayOutputStream2.toByteArray()); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/test/TestHibernate.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.hibernate.Criteria; 7 | import org.hibernate.Query; 8 | import org.hibernate.Session; 9 | import org.hibernate.Transaction; 10 | import org.hibernate.criterion.Restrictions; 11 | 12 | import protocol.Data.ChatData.ChatItem.ChatType; 13 | import protocol.Data.ChatData.ChatItem.TargetType; 14 | 15 | import model.Chatting; 16 | import model.Group; 17 | import model.HibernateSessionFactory; 18 | import model.User; 19 | 20 | public class TestHibernate { 21 | public static void main(String args[]){ 22 | add(); 23 | add2(); 24 | query(); 25 | query2(); 26 | } 27 | 28 | public static void add(){ 29 | Group p = new Group("group1"); 30 | // p.setGroupName("group1"); 31 | 32 | User u1 = new User(); 33 | User u2 = new User(); 34 | u1.setUserId("user1"); 35 | u1.setUserName("name1"); 36 | u1.setUserPassword("121"); 37 | u2.setUserId("user2"); 38 | u2.setUserName("name2"); 39 | u2.setUserPassword("122"); 40 | List memberList = new ArrayList(); 41 | memberList.add(u1); 42 | memberList.add(u2); 43 | p.setMemberList(memberList); 44 | 45 | Session session = HibernateSessionFactory.getSession(); 46 | Transaction trans = session.beginTransaction(); 47 | session.save(u1); 48 | session.save(u2); 49 | session.save(p); 50 | 51 | trans.commit(); 52 | session.close(); 53 | } 54 | 55 | public static void add2(){ 56 | Chatting chat = new Chatting("user1","user2",ChatType.TEXT,"this is a message",new Long(2015040611),0, TargetType.GROUP); 57 | Session session = HibernateSessionFactory.getSession(); 58 | Transaction trans = session.beginTransaction(); 59 | session.save(chat); 60 | 61 | trans.commit(); 62 | session.close(); 63 | } 64 | 65 | public static void query(){ 66 | Session session = HibernateSessionFactory.getSession(); 67 | Criteria criteria = session.createCriteria(Group.class); 68 | criteria.add(Restrictions.eq("groupName", "group1")); 69 | List list = criteria.list(); 70 | if(null != list && list.size()>0){ 71 | Group group = list.get(0); 72 | System.out.println(group.getGroupId()+" "+group.getGroupName()); 73 | for(int i=0;i0){ 85 | Chatting chat = (Chatting)list.get(0); 86 | System.out.println(chat.getSenderUserId()+" "+chat.getReceiverUserId()+" "+chat.getMessage()); 87 | } 88 | } 89 | 90 | public static void query3(){ 91 | Session session = HibernateSessionFactory.getSession(); 92 | Query query = session.createQuery("SELECT c.id, c.senderUserId,c.receiverUserId,c.chattingType,c.message,c.time"+ 93 | ",c.isGroup,c.groupId from Chatting c where id ="+1); 94 | List list = query.list(); 95 | for(int i=0;i() { 71 | @Override 72 | public void operationComplete(IoFuture future) { 73 | // Calendar calendar = Calendar.getInstance(); 74 | // System.out.println(calendar.get(Calendar.MINUTE) + ":" + calendar.get(Calendar.SECOND)); 75 | // System.out.println(future.isDone()); 76 | } 77 | }); 78 | } 79 | 80 | public void sessionOpened(IoSession session) throws Exception { 81 | System.out.println(session.isClosing()); 82 | } 83 | 84 | @Override 85 | public void sessionClosed(IoSession session) throws Exception { 86 | System.out.println(session.isConnected()); 87 | System.out.println(acceptor.getStatistics()); 88 | } 89 | 90 | @Override 91 | public void messageSent(IoSession session, Object message) throws Exception { 92 | // TODO Auto-generated method stub 93 | 94 | // super.messageSent(session, message); 95 | 96 | // System.out.println(message); 97 | // printStackTrace(Server111.class); 98 | } 99 | 100 | @Override 101 | public void exceptionCaught(IoSession session, Throwable cause) { 102 | Debug.log("throws exception"); 103 | Debug.log("session.toString()", session.toString()); 104 | Debug.log("cause.toString()", cause.toString()); 105 | Debug.log("Report Error Over!!"); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/model/User.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import javax.persistence.CascadeType; 7 | import javax.persistence.Column; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.Entity; 10 | import javax.persistence.Id; 11 | import javax.persistence.JoinTable; 12 | import javax.persistence.ManyToMany; 13 | import javax.persistence.Table; 14 | 15 | import org.hibernate.annotations.Cache; 16 | import org.hibernate.annotations.CacheConcurrencyStrategy; 17 | 18 | import protocol.Data.UserData.UserItem; 19 | 20 | 21 | @Entity 22 | @Table(name="user") 23 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 24 | public class User implements Serializable { 25 | // public static final String TABLE_NAME = User.class.getSimpleName(); 26 | public static final String TABLE_NAME = "user"; 27 | public static final String TABLE_USER_ID = "user_id"; 28 | public static final String HQL_USER_ID = "userId"; 29 | 30 | /** 31 | * 32 | */ 33 | private static final long serialVersionUID = 1L; 34 | 35 | private String userId; 36 | private String userName; 37 | private String userPassword; 38 | private int headIndex; 39 | private List friends; 40 | private List groups; 41 | 42 | public User(){ 43 | 44 | } 45 | 46 | public User(String userId,String userName,String userPassword){ 47 | this.userId=userId; 48 | this.userName=userName; 49 | this.userPassword=userPassword; 50 | } 51 | 52 | @Id 53 | @Column(name="user_id",columnDefinition = "char(20) COMMENT '微信号'") 54 | public String getUserId() { 55 | return userId; 56 | } 57 | public void setUserId(String userId) { 58 | this.userId = userId; 59 | } 60 | 61 | @Column(name="user_name",columnDefinition = "char(20) COMMENT '昵称'") 62 | public String getUserName() { 63 | return userName; 64 | } 65 | public void setUserName(String userName) { 66 | this.userName = userName; 67 | } 68 | 69 | @Column(name="user_password",columnDefinition = "char(20) COMMENT '密码'") 70 | public String getUserPassword() { 71 | return userPassword; 72 | } 73 | public void setUserPassword(String userPassword) { 74 | this.userPassword = userPassword; 75 | } 76 | 77 | 78 | @Column(name="user_headIndex",columnDefinition = "int(4) COMMENT '头像编号'") 79 | public int getHeadIndex() { 80 | return headIndex; 81 | } 82 | 83 | public void setHeadIndex(int headIndex) { 84 | this.headIndex = headIndex; 85 | } 86 | 87 | public static long getSerialversionuid() { 88 | return serialVersionUID; 89 | } 90 | 91 | @ManyToMany(targetEntity=User.class) 92 | @JoinTable(name = "user_friends", 93 | joinColumns = @JoinColumn(name = "user_id"), 94 | inverseJoinColumns = @JoinColumn(name = "friend_id")) 95 | public List getFriends() { 96 | return friends; 97 | } 98 | public void setFriends(List friends) { 99 | this.friends = friends; 100 | } 101 | 102 | @ManyToMany(targetEntity = Group.class, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) 103 | @JoinTable(name = "group_members", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "group_id")) 104 | public List getGroups() { 105 | return groups; 106 | } 107 | public void setGroups(List groups) { 108 | this.groups = groups; 109 | } 110 | 111 | 112 | 113 | public String toString(){ 114 | return this.getUserId()+" "+this.getUserName(); 115 | } 116 | 117 | public static UserItem.Builder createUserItemBuilder(User user) { 118 | UserItem.Builder builder = UserItem.newBuilder(); 119 | builder.setHeadIndex(user.getHeadIndex()); 120 | builder.setUserId(user.getUserId()); 121 | builder.setUserName(user.getUserName()); 122 | return builder; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/JUnit/TestCreateGroupChatting.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | import java.net.UnknownHostException; 7 | import java.util.Calendar; 8 | 9 | import org.junit.Test; 10 | 11 | import protocol.ProtoHead; 12 | import protocol.Data.ChatData.ChatItem; 13 | import protocol.Data.GroupData.GroupItem; 14 | import protocol.Msg.ChangeGroupMsg.ChangeGroupSync; 15 | import protocol.Msg.CreateGroupChatMsg.CreateGroupChatReq; 16 | import protocol.Msg.CreateGroupChatMsg.CreateGroupChatRsp; 17 | import protocol.Msg.LoginMsg.LoginRsp; 18 | import protocol.Msg.ReceiveChatMsg.ReceiveChatSync; 19 | import server.NetworkPacket; 20 | import tools.DataTypeTranslater; 21 | 22 | public class TestCreateGroupChatting { 23 | 24 | private CreateGroupChatRsp createGroupChatting(ClientSocket clientSocket, String[] userList) throws IOException { 25 | CreateGroupChatReq.Builder builder = CreateGroupChatReq.newBuilder(); 26 | for (String s : userList) 27 | builder.addUserId(s); 28 | 29 | clientSocket.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.CREATE_GROUP_CHAT_REQ_VALUE, builder 30 | .build().toByteArray())); 31 | 32 | byte[] arrayBytes; 33 | for (int i = 0; i < 10; i++) { 34 | arrayBytes = clientSocket.readFromServerWithoutKeepAlive(); 35 | 36 | if (NetworkPacket.getMessageType(arrayBytes) != ProtoHead.ENetworkMessage.CREATE_GROUP_CHAT_RSP) 37 | continue; 38 | 39 | return CreateGroupChatRsp.parseFrom(NetworkPacket.getMessageObjectBytes(arrayBytes)); 40 | } 41 | return null; 42 | } 43 | 44 | /** 45 | * 测试正常情况 46 | * 47 | * @throws IOException 48 | * @throws UnknownHostException 49 | */ 50 | @Test 51 | public void test() throws UnknownHostException, IOException { 52 | String user1 = "a", user2 = "b"; 53 | ClientSocket clientSocket1 = new ClientSocket(); 54 | ClientSocket clientSocket2 = new ClientSocket(); 55 | 56 | // user1 登陆 57 | System.out.println(user1 + " login"); 58 | LoginRsp.ResultCode resultCode = clientSocket1.login(user1, user1); 59 | assertEquals(resultCode, LoginRsp.ResultCode.SUCCESS); 60 | System.out.println(resultCode); 61 | 62 | // user2登陆 63 | System.out.println(user2 + " login"); 64 | assertEquals(clientSocket2.login(user2, user2), LoginRsp.ResultCode.SUCCESS); 65 | 66 | // 创建成功? 67 | System.out.println(user1 + " create Group"); 68 | CreateGroupChatRsp response = createGroupChatting(clientSocket1, new String[] { "b" }); 69 | assertEquals(response.getResultCode(), CreateGroupChatRsp.ResultCode.SUCCESS); 70 | System.out.println("GroupId : " + response.getGroupChatId()); 71 | 72 | // user2接收到有新群消息 73 | System.out.println(user2 + " Wait Message"); 74 | byte[] byteArray; 75 | for (int i = 0; i < 2; i++) { 76 | byteArray = clientSocket2.readFromServerWithoutKeepAlive(); 77 | System.out.println("Receive one Message!"); 78 | if (NetworkPacket.getMessageType(byteArray) == ProtoHead.ENetworkMessage.CHANGE_GROUP_SYNC) { 79 | // 成员变化通知 80 | System.out.println("成员变化通知"); 81 | ChangeGroupSync changeGroupSync = ChangeGroupSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 82 | GroupItem groupItem = changeGroupSync.getGroupItem(); 83 | System.out.println("CHANGE_GROUP_SYNC : " + user2 + " : " + ClientSocket.getGroupItemInfo(groupItem)); 84 | assertEquals(groupItem.getCreaterUserId(), user1); 85 | assertEquals(groupItem.getMemberUserIdCount(), 2); 86 | } else if (NetworkPacket.getMessageType(byteArray) == ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC) { 87 | ReceiveChatSync receiveChatting = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 88 | ChatItem chatItem2 = receiveChatting.getChatData(0); 89 | 90 | // 收到群聊消息(A 我已经把 B,C 拉入群聊) 91 | System.out.println("RECEIVE_CHAT_SYNC : " + user2 + " : " + ClientSocket.getChatItemInfo(chatItem2)); 92 | } 93 | } 94 | 95 | clientSocket1.close(); 96 | clientSocket2.close(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/server/ClientRequest_Dispatcher.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | 4 | import exception.NoIpException; 5 | 6 | import protocol.ProtoHead; 7 | import tools.Debug; 8 | 9 | /** 10 | * 用switch进行请求分发 11 | * 12 | * @author Feng 13 | * 14 | */ 15 | public class ClientRequest_Dispatcher { 16 | // public static ClientRequest_Dispatcher instance = new 17 | // ClientRequest_Dispatcher(); 18 | private Server_User server_User; 19 | private Server_Friend server_Friend; 20 | private Server_Chatting server_Chatting; 21 | 22 | public Server_User getServer_User() { 23 | return server_User; 24 | } 25 | 26 | public void setServer_User(Server_User server_User) { 27 | this.server_User = server_User; 28 | } 29 | 30 | public Server_Friend getServer_Friend() { 31 | return server_Friend; 32 | } 33 | 34 | public void setServer_Friend(Server_Friend server_Friend) { 35 | this.server_Friend = server_Friend; 36 | } 37 | 38 | public Server_Chatting getServer_Chatting() { 39 | return server_Chatting; 40 | } 41 | 42 | public void setServer_Chatting(Server_Chatting server_Chatting) { 43 | this.server_Chatting = server_Chatting; 44 | } 45 | 46 | /** 47 | * 根据请求的类型分配给不同的处理器 48 | * 49 | * @param networkMessage 50 | * @author Feng 51 | */ 52 | public void dispatcher(NetworkPacket networkPacket) { 53 | // System.out.println("IP" + 54 | // networkMessage.ioSession.getRemoteAddress()); 55 | try { 56 | Debug.log("ClientRequest_Dispatcher", "Client(" + ServerModel.getIoSessionKey(networkPacket.ioSession) 57 | + ")'s request type is : " + networkPacket.getMessageType().toString()); 58 | } catch (Exception e1) { 59 | } 60 | 61 | try { 62 | switch (networkPacket.getMessageType().getNumber()) { 63 | // Client回复心跳包 64 | // case ProtoHead.ENetworkMessage.KEEP_ALIVE_SYNC_VALUE: 65 | // server_User.keepAlive(networkPacket); 66 | // break; 67 | case ProtoHead.ENetworkMessage.REGISTER_REQ_VALUE: 68 | server_User.register(networkPacket); 69 | break; 70 | case ProtoHead.ENetworkMessage.LOGIN_REQ_VALUE: 71 | server_User.login(networkPacket); 72 | break; 73 | case ProtoHead.ENetworkMessage.PERSONALSETTINGS_REQ_VALUE: 74 | server_User.personalSettings(networkPacket); 75 | break; 76 | case ProtoHead.ENetworkMessage.GET_USERINFO_REQ_VALUE: 77 | server_Friend.getUserInfo(networkPacket); 78 | break; 79 | case ProtoHead.ENetworkMessage.ADD_FRIEND_REQ_VALUE: 80 | server_Friend.addFriend(networkPacket); 81 | break; 82 | case ProtoHead.ENetworkMessage.DELETE_FRIEND_REQ_VALUE: 83 | server_Friend.deleteFriend(networkPacket); 84 | break; 85 | // 另一个人登陆,本用户被踢下的通知的回复 86 | // case ProtoHead.ENetworkMessage.OFFLINE_SYNC_VALUE: 87 | // server_User.clientOfflineResponse(networkPacket); 88 | // break; 89 | case ProtoHead.ENetworkMessage.LOGOUT_REQ_VALUE: 90 | server_User.logout(networkPacket); 91 | break; 92 | case ProtoHead.ENetworkMessage.GET_PERSONALINFO_REQ_VALUE: 93 | server_User.getPersonalInfo(networkPacket); 94 | break; 95 | // client发送消息 96 | case ProtoHead.ENetworkMessage.SEND_CHAT_REQ_VALUE: 97 | server_Chatting.clientSendChatting(networkPacket); 98 | break; 99 | // 服务器向客户端发送未接收消息,客户端的回答 100 | // case ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC_VALUE: 101 | // server_Chatting.clientReceiveChatting(networkPacket); 102 | // break; 103 | // 创建群聊 104 | case ProtoHead.ENetworkMessage.CREATE_GROUP_CHAT_REQ_VALUE: 105 | server_Chatting.createGroupChatting(networkPacket); 106 | break; 107 | // 修改群聊成员 108 | case ProtoHead.ENetworkMessage.CHANGE_GROUP_REQ_VALUE: 109 | server_Chatting.changeGroup(networkPacket); 110 | break; 111 | // 获取群资料 112 | case ProtoHead.ENetworkMessage.GET_GROUP_INFO_REQ_VALUE: 113 | server_Chatting.getGroupInfo(networkPacket); 114 | break; 115 | default: 116 | break; 117 | } 118 | } catch (NoIpException e) { 119 | e.printStackTrace(); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/server/Server.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import javax.annotation.Resource; 7 | 8 | import model.HibernateSessionFactory; 9 | 10 | import org.apache.log4j.Logger; 11 | import org.apache.log4j.PropertyConfigurator; 12 | import org.hibernate.Session; 13 | import org.springframework.context.ApplicationContext; 14 | import org.springframework.context.support.FileSystemXmlApplicationContext; 15 | 16 | import tools.AutoResponseClient; 17 | 18 | /** 19 | * 服务器启动器 20 | * 21 | * @author Feng 22 | * 23 | */ 24 | public class Server { 25 | public static boolean keepAliveSwitch = true; 26 | // public static boolean keepAliveSwitch = false; 27 | static Logger logger = Logger.getLogger(Server.class); 28 | 29 | public static Server instance; 30 | private ServerNetwork serverNetwork; 31 | private ServerModel serverModel; 32 | private ServerModel_Chatting serverModel_Chatting; 33 | 34 | public Server() throws IOException { 35 | // // 启动网络层 36 | // // ServerNetwork.instance.init(); 37 | // 38 | // // 启动逻辑层 39 | // // ServerModel.instance.init(); 40 | // init(); 41 | } 42 | 43 | /** 44 | * 初始化 45 | * @author Feng 46 | */ 47 | // public void init(){ 48 | // try { 49 | // serverNetwork.init(); 50 | // 51 | // // 开启自动回复器 52 | // new AutoResponseClient(); 53 | // } catch (IOException e) { 54 | // e.printStackTrace(); 55 | // } 56 | // serverModel.init(); 57 | // serverModel_Chatting.init(); 58 | // } 59 | 60 | public static Server getServer() { 61 | return instance; 62 | } 63 | 64 | public static void setServer(Server server) { 65 | Server.instance = server; 66 | } 67 | 68 | public ServerNetwork getServerNetwork() { 69 | return serverNetwork; 70 | } 71 | 72 | public void setServerNetwork(ServerNetwork serverNetwork) { 73 | this.serverNetwork = serverNetwork; 74 | } 75 | 76 | public ServerModel getServerModel() { 77 | return serverModel; 78 | } 79 | 80 | public void setServerModel(ServerModel serverModel) { 81 | this.serverModel = serverModel; 82 | } 83 | 84 | 85 | public ServerModel_Chatting getServerModel_Chatting() { 86 | return serverModel_Chatting; 87 | } 88 | 89 | public void setServerModel_Chatting(ServerModel_Chatting serverModel_Chatting) { 90 | this.serverModel_Chatting = serverModel_Chatting; 91 | } 92 | 93 | public void onDestroy() { 94 | serverNetwork.onDestroy(); 95 | } 96 | 97 | public static void main(String[] args) throws IOException { 98 | String path = System.getProperty("user.dir"); 99 | logger.info(path); 100 | try{ 101 | String logConfigPath = "Log4JConfig.properties"; 102 | logger.info(logConfigPath); 103 | PropertyConfigurator.configure(logConfigPath); 104 | logger.info("log configure load success"); 105 | }catch(Exception e){ 106 | logger.info("log configure load fail"); 107 | e.printStackTrace(); 108 | } 109 | try{ 110 | Session session = HibernateSessionFactory.getSession(); 111 | session.close(); 112 | logger.info("数据库配置加载成功"); 113 | }catch(Exception e){ 114 | logger.error("数据库配置加载失败"); 115 | } 116 | // try{ 117 | // String springConfigPath = "src/applicationContext.xml"; 118 | // PropertyConfigurator.configure(springConfigPath); 119 | // logger.info("spring configure load success"); 120 | // }catch(Exception e){ 121 | // System.out.println("spring configure load fail"); 122 | // e.printStackTrace(); 123 | // } 124 | 125 | // File file = new File("src/applicationContext.xml"); 126 | // System.out.println(file.exists()); 127 | ApplicationContext ctx = new FileSystemXmlApplicationContext("applicationContext.xml"); 128 | ((ServerNetwork) ctx.getBean("ServerNetwork")).init(); 129 | ((ServerModel)ctx.getBean("ServerModel")).init(); 130 | ((MyLogger)ctx.getBean("MyLogger")).closeLoggerNotWant(); 131 | 132 | new AutoResponseClient(); 133 | // ServerNetwork serverNetwork = (ServerNetwork)ctx.getBean("ServerNetwork"); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/JUnit/TestSendGroupChatting.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | import java.net.UnknownHostException; 7 | import java.util.Calendar; 8 | 9 | import org.junit.Test; 10 | 11 | import protocol.ProtoHead; 12 | import protocol.Data.ChatData.ChatItem; 13 | import protocol.Data.ChatData.ChatItem.ChatType; 14 | import protocol.Data.ChatData.ChatItem.TargetType; 15 | import protocol.Msg.LoginMsg.LoginReq; 16 | import protocol.Msg.LoginMsg.LoginRsp; 17 | import protocol.Msg.ReceiveChatMsg; 18 | import protocol.Msg.ReceiveChatMsg.ReceiveChatSync; 19 | import protocol.Msg.SendChatMsg.SendChatReq; 20 | import protocol.Msg.SendChatMsg.SendChatRsp; 21 | 22 | import server.NetworkPacket; 23 | import test.Client111; 24 | import tools.DataTypeTranslater; 25 | 26 | /** 27 | * 测试群发消息 28 | * 29 | * @author Administrator 30 | * 31 | */ 32 | 33 | //@FixMethodOrder(MethodSorters.DEFAULT) 34 | public class TestSendGroupChatting { 35 | 36 | private SendChatRsp.ResultCode sendChatting(ClientSocket clientSocket, ChatItem.Builder chatItem) throws IOException { 37 | // 构建消息对象 38 | SendChatReq.Builder sendChattingBuilder = SendChatReq.newBuilder(); 39 | sendChattingBuilder.setChatData(chatItem); 40 | clientSocket.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.SEND_CHAT_REQ_VALUE, sendChattingBuilder 41 | .build().toByteArray())); 42 | 43 | byte[] byteArray; 44 | for (int i = 0; i < 10; i++) { 45 | byteArray = clientSocket.readFromServerWithoutKeepAlive(); 46 | if (NetworkPacket.getMessageType(byteArray) != ProtoHead.ENetworkMessage.SEND_CHAT_RSP) 47 | continue; 48 | 49 | return SendChatRsp.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)).getResultCode(); 50 | } 51 | return null; 52 | } 53 | 54 | @Test 55 | public void test1() throws UnknownHostException, IOException { 56 | ClientSocket clientSocket1 = new ClientSocket(); 57 | ClientSocket clientSocket2 = new ClientSocket(); 58 | ClientSocket clientSocket3; 59 | byte[] response; 60 | String user1 = "a", user2 = "b", user3 = "c", message = "a fuck b and c", groupId = "13"; 61 | 62 | // a,b 登陆 63 | assertEquals(clientSocket1.login(user1, user1), LoginRsp.ResultCode.SUCCESS); 64 | assertEquals(clientSocket2.login(user2, user2), LoginRsp.ResultCode.SUCCESS); 65 | System.out.println(user1 + " , " + user2 + " Login Over!"); 66 | 67 | // 构建消息对象 68 | ChatItem.Builder chatItem = ChatItem.newBuilder(); 69 | chatItem.setChatBody(message); 70 | chatItem.setSendUserId(user1); 71 | chatItem.setReceiveUserId(groupId); 72 | chatItem.setChatType(ChatType.TEXT); 73 | chatItem.setTargetType(TargetType.GROUP); 74 | 75 | // user1发送 76 | assertEquals(sendChatting(clientSocket1, chatItem), SendChatRsp.ResultCode.SUCCESS); 77 | System.out.println(user1 + " Send Chatting Over!"); 78 | 79 | // user2接收 80 | byte[] byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 81 | assertNotNull(byteArray); 82 | ReceiveChatSync receiveChatting = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 83 | ChatItem chatItem2 = receiveChatting.getChatData(0); 84 | assertEquals(chatItem2.getChatBody(), message); 85 | System.out.println(user2 + " Get Chatting"); 86 | // Calendar calendar = Calendar.getInstance(); 87 | // calendar.setTimeInMillis(chatItem2.getDate()-99999); 88 | System.out.println(ClientSocket.getChatItemInfo(chatItem2)); 89 | 90 | // user3接收 91 | clientSocket3 = new ClientSocket(); 92 | // user3登陆 93 | assertEquals(clientSocket3.login(user3, user3), LoginRsp.ResultCode.SUCCESS); 94 | 95 | byteArray = clientSocket3.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 96 | assertNotNull(byteArray); 97 | receiveChatting = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 98 | assertEquals(receiveChatting.getChatData(0).getChatBody(), message); 99 | System.out.println(user3 + " Get Chatting"); 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/model/test.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.hibernate.Criteria; 6 | import org.hibernate.Query; 7 | import org.hibernate.Session; 8 | import org.hibernate.Transaction; 9 | import org.hibernate.criterion.Restrictions; 10 | 11 | 12 | 13 | public class test { 14 | 15 | public static void main(String[] args) { 16 | add(); 17 | load(); 18 | query(); 19 | query2(); 20 | update(); 21 | delete(); 22 | 23 | HibernateSessionFactory.sessionFactory.close(); 24 | } 25 | 26 | private static void add(){ 27 | User user1 = new User(); 28 | user1.setUserId("user1"); 29 | user1.setUserName("name1"); 30 | user1.setUserPassword("121"); 31 | 32 | User user2 = new User(); 33 | user2.setUserId("user2"); 34 | user2.setUserName("name2"); 35 | user2.setUserPassword("122"); 36 | 37 | User user3 = new User(); 38 | user3.setUserId("user3"); 39 | user3.setUserName("username3"); 40 | user3.setUserPassword("123"); 41 | 42 | List friends = new ArrayList(); 43 | friends.add(user3); 44 | user2.setFriends(friends); 45 | 46 | Session session = HibernateSessionFactory.getSession(); 47 | Transaction trans = session.beginTransaction(); 48 | // session.persist(user1); 49 | // session.persist(user2); 50 | session.save(user1); 51 | session.save(user3); 52 | session.save(user2); 53 | trans.commit(); 54 | 55 | session.close(); 56 | } 57 | 58 | private static void load(){ 59 | Session session = HibernateSessionFactory.getSession(); 60 | User u = (User)session.load(User.class, "user2"); 61 | System.out.println("userInfo:"+u.getUserId()+" "+u.getUserName()+" "+u.getUserPassword()); 62 | List friends = u.getFriends(); 63 | System.out.print(" friends:"); 64 | for(int i=0;i list = criteria.list(); 90 | for(User u:list){ 91 | System.out.println("userInfo:"+u.getUserId()+" "+u.getUserName()+" "+u.getUserPassword()); 92 | List friends = u.getFriends(); 93 | System.out.print(" friends:"); 94 | for(int i=0;i loggerSet; 156 | public ArrayList logCalssList; 157 | 158 | public LoggerRule(LoggerType loggerType) { 159 | this.loggerType = loggerType; 160 | loggerSet = new HashSet(); 161 | logCalssList = new ArrayList(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/server/ServerNetwork.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.IOException; 4 | import java.net.InetAddress; 5 | import java.net.InetSocketAddress; 6 | import java.net.UnknownHostException; 7 | 8 | import org.apache.log4j.Logger; 9 | import org.apache.mina.core.buffer.IoBuffer; 10 | import org.apache.mina.core.filterchain.IoFilter; 11 | import org.apache.mina.core.future.IoFuture; 12 | import org.apache.mina.core.future.IoFutureListener; 13 | import org.apache.mina.core.future.WriteFuture; 14 | import org.apache.mina.core.service.IoAcceptor; 15 | import org.apache.mina.core.service.IoHandlerAdapter; 16 | import org.apache.mina.core.session.IdleStatus; 17 | import org.apache.mina.core.session.IoSession; 18 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 19 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 20 | import org.springframework.context.support.ClassPathXmlApplicationContext; 21 | 22 | import exception.NoIpException; 23 | import tools.DataTypeTranslater; 24 | import tools.Debug; 25 | 26 | /** 27 | * 服务器的网络层,负责网络交互 28 | * 29 | * @author Feng 30 | * 31 | */ 32 | public class ServerNetwork { 33 | // 轮询"等待client回复"的超时时间 34 | public static final long WAIT_CLIENT_RESPONSE_TIMEOUT = 3000; 35 | // 轮询"等待client回复"的重发次数 36 | public static final long WAIT_CLIENT_RESPONSE_TIMES = 3; 37 | 38 | // public static ServerNetwork instance = new ServerNetwork(); 39 | private ServerModel serverModel; 40 | private ClientRequest_Dispatcher clientRequest_Dispatcher; 41 | private MinaServerHandle minaServerHandle; 42 | private ProtocolCodecFilter protocolCodecFilter; 43 | private MyLogger myLogger; 44 | private InetAddress addr; 45 | 46 | Logger logger = Logger.getLogger(ServerNetwork.class); 47 | 48 | private InetSocketAddress inetSocketAddress; 49 | private IoAcceptor acceptor; 50 | 51 | public ServerNetwork() { 52 | } 53 | 54 | /** 55 | * 初始化 56 | * 57 | * @throws IOException 58 | * @author Feng 59 | */ 60 | public void init() { 61 | if (addr != null || minaServerHandle == null) 62 | return; 63 | 64 | // 显示IP地址 65 | try { 66 | addr = InetAddress.getLocalHost(); 67 | logger.info("IP address:" + addr.getHostAddress().toString()); 68 | logger.info("Host Name:" + addr.getHostName().toString()); 69 | 70 | } catch (UnknownHostException e1) { 71 | e1.printStackTrace(); 72 | } 73 | // Debug.log("Port Number:8081"); 74 | logger.debug("Port Number:8081"); 75 | 76 | acceptor = new NioSocketAcceptor(); 77 | // 指定编码解码器 78 | acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MinaEncoder(), new MinaDecoder())); 79 | // System.out.println("22222222222222222222222222"); 80 | if (myLogger == null) 81 | myLogger = new MyLogger(); 82 | // System.out.println(myLogger == null); 83 | acceptor.getFilterChain().addLast("Logger", myLogger); 84 | // System.out.println("codec " + (protocolCodecFilter == null)); 85 | // acceptor.getFilterChain().addLast("codec", protocolCodecFilter); 86 | acceptor.getSessionConfig().setMaxReadBufferSize(1024 * 8); 87 | // System.out.println("minaServerHandle :" + (minaServerHandle == 88 | // null)); 89 | acceptor.setHandler(minaServerHandle); 90 | // acceptor.setHandler(new MinaServerHandle()); 91 | try { 92 | acceptor.bind(new InetSocketAddress(8081)); 93 | } catch (IOException e) { 94 | e.printStackTrace(); 95 | logger.error("ServerNetwork : Acceptor bind Exception!;\n" + e.toString()); 96 | } 97 | 98 | // new ClassPathXmlApplicationContext("trapReceiverContext.xml"); 99 | } 100 | 101 | public void onDestroy() { 102 | acceptor.unbind(inetSocketAddress); 103 | } 104 | 105 | public ServerModel getServerModel() { 106 | return serverModel; 107 | } 108 | 109 | public void setServerModel(ServerModel serverModel) { 110 | this.serverModel = serverModel; 111 | } 112 | 113 | public ClientRequest_Dispatcher getClientRequest_Dispatcher() { 114 | return clientRequest_Dispatcher; 115 | } 116 | 117 | public void setClientRequest_Dispatcher(ClientRequest_Dispatcher clientRequest_Dispatcher) { 118 | this.clientRequest_Dispatcher = clientRequest_Dispatcher; 119 | } 120 | 121 | public MinaServerHandle getMinaServerHandle() { 122 | return minaServerHandle; 123 | } 124 | 125 | public void setMinaServerHandle(MinaServerHandle minaServerHandle) { 126 | this.minaServerHandle = minaServerHandle; 127 | } 128 | 129 | public ProtocolCodecFilter getProtocolCodecFilter() { 130 | return protocolCodecFilter; 131 | } 132 | 133 | public void setProtocolCodecFilter(ProtocolCodecFilter protocolCodecFilter) { 134 | this.protocolCodecFilter = protocolCodecFilter; 135 | } 136 | 137 | public MyLogger getMyLogger() { 138 | return myLogger; 139 | } 140 | 141 | public void setMyLogger(MyLogger myLogger) { 142 | this.myLogger = myLogger; 143 | } 144 | 145 | /** 146 | * 添加一个等待客户端回复的监听(服务器向客户端发送消息后,要求客户端回复) 147 | * 148 | * @param ioSession 149 | * @param key 150 | * @param messageHasSentww 151 | * @author Feng 152 | */ 153 | public void sendToClient(IoSession ioSession, PacketFromServer packetFromServer) { 154 | sendToClient(new WaitClientResponse(ioSession, packetFromServer)); 155 | } 156 | 157 | public void sendToClient(final WaitClientResponse waitClientResponse) { 158 | sendToClient(waitClientResponse, 0); 159 | } 160 | 161 | private void sendToClient(final WaitClientResponse waitClientResponse, final int times) { 162 | try { 163 | if (serverModel.getClientUserFromTable(waitClientResponse.ioSession) == null) { 164 | // 用户已掉线, 调用删除前的回调,然后删除 165 | if (waitClientResponse.waitClientResponseCallBack != null) 166 | waitClientResponse.waitClientResponseCallBack.beforeDelete(); 167 | return; 168 | } 169 | // 用户在线,重发 170 | WriteFuture writeFuture = waitClientResponse.ioSession.write(waitClientResponse.packetFromServer); 171 | // writeFuture.awaitUninterruptibly(WAIT_CLIENT_RESPONSE_TIMEOUT); 172 | writeFuture.addListener(new IoFutureListener() { 173 | @Override 174 | public void operationComplete(IoFuture future) { 175 | if (((WriteFuture) future).isWritten()) 176 | return; 177 | else { 178 | // Debug.log("ServerModel", 179 | // "Wait for Client(" + 180 | // serverModel.getIoSessionKey(waitClientResponse.ioSession) 181 | // + ") response timeout!"); 182 | try { 183 | logger.info("ServerModel Wait for Client(" 184 | + serverModel.getIoSessionKey(waitClientResponse.ioSession) + ") response timeout!"); 185 | 186 | if (times < WAIT_CLIENT_RESPONSE_TIMES) { 187 | // 小于重发极限次数,重发 188 | // Debug.log("ServerModel", "Client(" + 189 | // serverModel.getIoSessionKey(waitClientResponse.ioSession) 190 | // + ") online,send again!"); 191 | logger.info("ServerModel Client(" + serverModel.getIoSessionKey(waitClientResponse.ioSession) 192 | + ") online,send again!"); 193 | sendToClient(waitClientResponse, times + 1); 194 | } else { 195 | // 大于重发极限次数,抛弃 196 | logger.info("To many times, abandon!"); 197 | return; 198 | } 199 | } catch (Exception e) { 200 | } 201 | } 202 | } 203 | }); 204 | } catch (NoIpException e) { 205 | e.printStackTrace(); 206 | if (waitClientResponse.waitClientResponseCallBack != null) 207 | waitClientResponse.waitClientResponseCallBack.beforeDelete(); 208 | return; 209 | } 210 | } 211 | 212 | /** 213 | * Mina网络连接回调方法 214 | * 215 | * @author Feng 216 | * 217 | */ 218 | } 219 | -------------------------------------------------------------------------------- /src/JUnit/ClientSocket.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.net.UnknownHostException; 8 | 9 | import protocol.ProtoHead; 10 | import protocol.Data.ChatData.ChatItem; 11 | import protocol.Data.GroupData.GroupItem; 12 | import protocol.Msg.LogoutMsg; 13 | import protocol.Msg.LoginMsg.LoginReq; 14 | import protocol.Msg.LoginMsg.LoginRsp; 15 | import protocol.Msg.LogoutMsg.LogoutRsp; 16 | 17 | import server.NetworkPacket; 18 | import tools.DataTypeTranslater; 19 | 20 | /** 21 | * 作为测试用例调用Socket前的初始化 22 | * 23 | * @author Feng 24 | * 25 | */ 26 | public class ClientSocket { 27 | public static final int HEAD_INT_SIZE = 4; 28 | public Socket socket; 29 | public InputStream inputStream; 30 | public OutputStream outputStream; 31 | 32 | // String host = "192.168.45.17"; // 要连接的服务端IP地址 33 | // public static final String host = "104.224.165.21"; // 要连接的服务端IP地址 34 | 35 | public String host = "127.0.0.1"; // 要连接的服务端IP地址 36 | // public String host = "104.224.165.21"; // 要连接的服务端IP地址 37 | 38 | // String host = "192.168.1.103"; // 要连接的服务端IP地址 39 | // String host = "192.168.45.11"; // 要连接的服务端IP地址 40 | // String host = "192.168.45.34"; // 要连接的服务端IP地址 41 | 42 | int port = 8081; // 要连接的服务端对应的监听端口 43 | 44 | public ClientSocket() throws UnknownHostException, IOException { 45 | link(); 46 | } 47 | 48 | /** 49 | * 连接Socket 50 | * 51 | * @throws UnknownHostException 52 | * @throws IOException 53 | * @author Feng 54 | */ 55 | public void link() throws UnknownHostException, IOException { 56 | socket = new Socket(host, port); 57 | inputStream = socket.getInputStream(); 58 | outputStream = socket.getOutputStream(); 59 | } 60 | 61 | /** 62 | * 关闭连接 63 | * 64 | * @throws IOException 65 | */ 66 | public void close() throws IOException { 67 | inputStream.close(); 68 | outputStream.close(); 69 | socket.close(); 70 | } 71 | 72 | /** 73 | * 处理服务器回复问题 74 | * 75 | * @author Feng 76 | * @return byte[] 77 | * @throws IOException 78 | */ 79 | public byte[] readFromServer() throws IOException { 80 | byte[] sizebyte = new byte[4]; 81 | 82 | inputStream.read(sizebyte); 83 | int size = DataTypeTranslater.bytesToInt(sizebyte, 0); 84 | byte[] byteArray = new byte[size]; 85 | for (int i = 0; i < DataTypeTranslater.INT_SIZE; i++) 86 | byteArray[i] = sizebyte[i]; 87 | 88 | inputStream.read(byteArray, HEAD_INT_SIZE, size - HEAD_INT_SIZE); 89 | // inputStream.read(byteArray); 90 | byteArray = cutResult(byteArray); 91 | return byteArray; 92 | 93 | // ByteArrayOutputStream byteArrayOutputStream = new 94 | // ByteArrayOutputStream(); 95 | // int data; 96 | // while (true) { 97 | // if ((data = inputStream.read()) == -1) 98 | // break; 99 | // byteArrayOutputStream.write(data); 100 | // } 101 | 102 | // inputStream.read(byteArray); 103 | // byteArray = cutResult(byteArray); 104 | 105 | // return byteArray; 106 | // byte[] byteArray = byteArrayOutputStream.toByteArray(); 107 | // byteArrayOutputStream.close(); 108 | // System.out.println("length : " + byteArray.length); 109 | // System.out.println(byteArray); 110 | // 111 | // return byteArray; 112 | } 113 | 114 | /** 115 | * 读取服务器发来的非心跳包 116 | * 117 | * @return 118 | * @throws IOException 119 | */ 120 | public byte[] readFromServerWithoutKeepAlive() throws IOException { 121 | byte[] byteArray; 122 | 123 | while (true) { 124 | byteArray = readFromServer(); 125 | // 不是KeepAlive(心跳包就返回) 126 | if (NetworkPacket.getMessageType(byteArray) != ProtoHead.ENetworkMessage.KEEP_ALIVE_SYNC) { 127 | // showBytes(byteArray); 128 | return byteArray; 129 | } 130 | 131 | } 132 | } 133 | 134 | public byte[] readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage type) throws IOException { 135 | byte[] byteArray; 136 | for (int i = 0; i < 10; i++) { 137 | byteArray = readFromServerWithoutKeepAlive(); 138 | 139 | if (NetworkPacket.getMessageType(byteArray) == type) 140 | return byteArray; 141 | } 142 | return null; 143 | } 144 | 145 | /** 146 | * 向服务器传输byte[] 147 | * 148 | * @param arrayBytes 149 | * @throws IOException 150 | */ 151 | public void writeToServer(byte[] arrayBytes) throws IOException { 152 | // outputStream = socket.getOutputStream(); 153 | // showBytes(arrayBytes); 154 | outputStream.write(arrayBytes); 155 | // outputStream.close(); 156 | } 157 | 158 | /** 159 | * 用于剪切从服务器发过来的byte[] 160 | * 161 | * @param byteArray 162 | * @return 163 | */ 164 | public byte[] cutResult(byte[] byteArray) { 165 | int size = DataTypeTranslater.bytesToInt(byteArray, 0); 166 | byte[] result = new byte[size]; 167 | for (int i = 0; i < size; i++) 168 | result[i] = byteArray[i]; 169 | 170 | return result; 171 | } 172 | 173 | /** 174 | * 登陆 175 | * 176 | * @param userId 177 | * @param userPassword 178 | * @return 179 | * @throws IOException 180 | * @author Feng 181 | */ 182 | public LoginRsp.ResultCode login(String userId, String userPassword) throws IOException { 183 | byte[] response; 184 | 185 | LoginReq.Builder loginBuilder = LoginReq.newBuilder(); 186 | loginBuilder.setUserId(userId); 187 | loginBuilder.setUserPassword(userPassword); 188 | 189 | writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.LOGIN_REQ_VALUE, loginBuilder.build().toByteArray())); 190 | for (int i = 0; i < 10; i++) { 191 | response = readFromServerWithoutKeepAlive(); 192 | if (NetworkPacket.getMessageType(response) != ProtoHead.ENetworkMessage.LOGIN_RSP) 193 | continue; 194 | 195 | LoginRsp loginResponse = LoginRsp.parseFrom(NetworkPacket.getMessageObjectBytes(response)); 196 | return loginResponse.getResultCode(); 197 | } 198 | return LoginRsp.ResultCode.FAIL; 199 | } 200 | 201 | public LogoutRsp.ResultCode logout() throws IOException { 202 | LogoutMsg.LogoutReq.Builder builder = LogoutMsg.LogoutReq.newBuilder(); 203 | byte[] byteArray = NetworkPacket.packMessage(ProtoHead.ENetworkMessage.LOGOUT_REQ.getNumber(), builder.build() 204 | .toByteArray()); 205 | 206 | writeToServer(byteArray); 207 | 208 | for (int i = 0; i < 10; i++) { 209 | byteArray = readFromServerWithoutKeepAlive(); 210 | if (NetworkPacket.getMessageType(byteArray) == ProtoHead.ENetworkMessage.LOGOUT_RSP) { 211 | return LogoutRsp.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)).getResultCode(); 212 | } 213 | } 214 | return LogoutRsp.ResultCode.FAIL; 215 | } 216 | 217 | /** 218 | * 测试用,查看收到的所有byte 219 | * 220 | * @param arrayBytes 221 | * @author Feng 222 | */ 223 | private void showBytes(byte[] arrayBytes) { 224 | // System.out.println("read from Server:"); 225 | System.out.println("Show a Message:"); 226 | for (byte b : arrayBytes) 227 | System.out.print(b + " "); 228 | System.out.println(); 229 | System.out.println("Size : " + DataTypeTranslater.bytesToInt(arrayBytes, NetworkPacket.getSizeStartIndex())); 230 | System.out.println("MessageId : " + DataTypeTranslater.bytesToInt(NetworkPacket.getMessageID(arrayBytes), 0)); 231 | System.out.println("Message Type : 1" + NetworkPacket.getMessageType(arrayBytes)); 232 | System.out.println("Message Body : " + NetworkPacket.getMessageObjectBytes(arrayBytes)); 233 | } 234 | 235 | public static String getGroupItemInfo(GroupItem groupItem) { 236 | return "GroupId : " + groupItem.getCreaterUserId() + "; Creater : " + groupItem.getCreaterUserId() + "; Member : " 237 | + groupItem.getMemberUserIdList().toString() + "; GroupName : " + groupItem.getGroupName(); 238 | } 239 | 240 | public static String getChatItemInfo(ChatItem chatItem) { 241 | return "Sender : " + chatItem.getSendUserId() 242 | + "; receiver : " + chatItem.getReceiveUserId() 243 | + "; TargetType : " + chatItem.getTargetType() 244 | + "; type : " + chatItem.getChatType().toString() 245 | + "; body : " + chatItem.getChatBody() 246 | + "; Date : " + DataTypeTranslater.getData(chatItem.getDate()); 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /src/tools/HttpClient.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | public class HttpClient { 3 | 4 | } 5 | // 6 | //import java.io.BufferedReader; 7 | //import java.io.ByteArrayOutputStream; 8 | //import java.io.DataOutputStream; 9 | //import java.io.FileInputStream; 10 | //import java.io.IOException; 11 | //import java.io.InputStreamReader; 12 | //import java.io.OutputStream; 13 | //import java.io.PrintWriter; 14 | //import java.net.HttpURLConnection; 15 | //import java.net.URL; 16 | //import java.net.URLConnection; 17 | //import java.util.List; 18 | //import java.util.Map; 19 | // 20 | //import server_HTTP.ServletServer; 21 | // 22 | //public class HttpClient { 23 | // /** 24 | // * 向指定URL发送GET方法的请求 25 | // * 26 | // * @param url 27 | // * 发送请求的URL 28 | // * @param param 29 | // * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 30 | // * @return URL 所代表远程资源的响应结果 31 | // */ 32 | // public static String sendGet(String url, String param) { 33 | // String result = ""; 34 | // BufferedReader in = null; 35 | // try { 36 | // String urlNameString = url + "?" + param; 37 | // URL realUrl = new URL(urlNameString); 38 | // // 打开和URL之间的连接 39 | // URLConnection connection = realUrl.openConnection(); 40 | // // 设置通用的请求属性 41 | // connection.setRequestProperty("accept", "*/*"); 42 | // connection.setRequestProperty("connection", "Keep-Alive"); 43 | // connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 44 | // // 建立实际的连接 45 | // connection.connect(); 46 | // // 获取所有响应头字段 47 | // Map> map = connection.getHeaderFields(); 48 | // // 遍历所有的响应头字段 49 | // for (String key : map.keySet()) { 50 | // System.out.println(key + "--->" + map.get(key)); 51 | // } 52 | // // 定义 BufferedReader输入流来读取URL的响应 53 | // in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 54 | // String line; 55 | // while ((line = in.readLine()) != null) { 56 | // result += line; 57 | // } 58 | // } catch (Exception e) { 59 | // System.out.println("发送GET请求出现异常!" + e); 60 | // e.printStackTrace(); 61 | // } 62 | // // 使用finally块来关闭输入流 63 | // finally { 64 | // try { 65 | // if (in != null) { 66 | // in.close(); 67 | // } 68 | // } catch (Exception e2) { 69 | // e2.printStackTrace(); 70 | // } 71 | // } 72 | // return result; 73 | // } 74 | // 75 | // /** 76 | // * 向指定 URL 发送POST方法的请求 77 | // * 78 | // * @param url 79 | // * 发送请求的 URL 80 | // * @param param 81 | // * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 82 | // * @return 所代表远程资源的响应结果 83 | // */ 84 | // public static String sendPost(String url, String param) { 85 | // PrintWriter out = null; 86 | // BufferedReader in = null; 87 | // String result = ""; 88 | // try { 89 | // URL realUrl = new URL(url); 90 | // // 打开和URL之间的连接 91 | // URLConnection conn = realUrl.openConnection(); 92 | // // 设置通用的请求属性 93 | // conn.setRequestProperty("accept", "*/*"); 94 | // conn.setRequestProperty("connection", "Keep-Alive"); 95 | // conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 96 | // // 发送POST请求必须设置如下两行 97 | // conn.setDoOutput(true); 98 | // conn.setDoInput(true); 99 | // // 获取URLConnection对象对应的输出流 100 | // out = new PrintWriter(conn.getOutputStream()); 101 | // // 发送请求参数 102 | // out.print(param); 103 | // 104 | // // 发送图片 105 | // OutputStream outputStream = conn.getOutputStream(); 106 | // 107 | // // flush输出流的缓冲 108 | // out.flush(); 109 | // // 定义BufferedReader输入流来读取URL的响应 110 | // in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 111 | // String line; 112 | // while ((line = in.readLine()) != null) { 113 | // result += line; 114 | // } 115 | // } catch (Exception e) { 116 | // System.out.println("发送 POST 请求出现异常!" + e); 117 | // e.printStackTrace(); 118 | // } 119 | // // 使用finally块来关闭输出流、输入流 120 | // finally { 121 | // try { 122 | // if (out != null) { 123 | // out.close(); 124 | // } 125 | // if (in != null) { 126 | // in.close(); 127 | // } 128 | // } catch (IOException ex) { 129 | // ex.printStackTrace(); 130 | // } 131 | // } 132 | // return result; 133 | // } 134 | // 135 | // public HttpClient() { 136 | // 137 | // } 138 | // 139 | // // public static void main(String args[]) { 140 | // // // new HttpClient(); 141 | // // sendPost("http://192.168.45.17:8080/MiniWechat/TransferFile", 142 | // // "type=Image&imageName=1.jpg"); 143 | // // } 144 | // 145 | // static String sessionId = ""; 146 | // 147 | // public static String getPicBASE64() { 148 | // String picPath = "D:/1.jpg"; 149 | // String content = ""; 150 | // try { 151 | // FileInputStream fileForInput = new FileInputStream(picPath); 152 | // byte[] bytes = new byte[fileForInput.available()]; 153 | // fileForInput.read(bytes); 154 | // content = new sun.misc.BASE64Encoder().encode(bytes); // 具体的编码方法 155 | // fileForInput.close(); 156 | // // System.out.println(content.length()); 157 | // } catch (Exception e) { 158 | // e.printStackTrace(); 159 | // } 160 | // return content; 161 | // } 162 | // 163 | // public static void main(String[] args) throws Exception { 164 | // URL url = new URL("http://192.168.45.17:8080/MiniWechat/TransferFile"); 165 | // HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 166 | // connection.setDoOutput(true); 167 | // // Read from the connection. Default is true. 168 | // connection.setDoInput(true); 169 | // // Set the post method. Default is GET 170 | // connection.setRequestMethod("POST"); 171 | // // Post cannot use caches 172 | // // Post 请求不能使用缓存 173 | // connection.setUseCaches(false); 174 | // // This method takes effects to 175 | // // every instances of this class. 176 | // // URLConnection.setFollowRedirects是static函数,作用于所有的URLConnection对象。 177 | // // connection.setFollowRedirects(true); 178 | // // This methods only 179 | // // takes effacts to this 180 | // // instance. 181 | // // URLConnection.setInstanceFollowRedirects是成员函数,仅作用于当前函数 182 | // connection.setInstanceFollowRedirects(false); 183 | // // Set the content type to urlencoded, 184 | // // because we will write 185 | // // some URL-encoded content to the 186 | // // connection. Settings above must be set before connect! 187 | // // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的 188 | // // 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode 189 | // // 进行编码 190 | // connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 191 | // // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成, 192 | // // 要注意的是connection.getOutputStream会隐含的进行connect。 193 | // connection.connect(); 194 | // Long sendTime = System.currentTimeMillis(); 195 | // DataOutputStream out = new DataOutputStream(connection.getOutputStream()); 196 | // // 要传的参数 197 | //// String content = URLEncoder.encode("type", "UTF-8") + "=" + URLEncoder.encode("UpdateImage", "UTF-8"); 198 | //// content += "&" + URLEncoder.encode("imageName", "UTF-8") + "=" + URLEncoder.encode("1.jpg", "UTF-8"); 199 | // String content = "type=UpdateImage&imageName=1.jpg&"; 200 | // // 得到图片的base64编码 201 | //// content = content + "&" + URLEncoder.encode("file", "UTF-8") + "=" + URLEncoder.encode(getPicBASE64(), "UTF-8"); 202 | // 203 | // ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 204 | // outputStream.write(content.getBytes()); 205 | //// System.out.println(ServletServer.CLIENT_PATH + "1.jpg"); 206 | // outputStream.write(DataTypeTranslater.fileToByte(ServletServer.CLIENT_PATH + "1.jpg")); 207 | // 208 | // out.write(outputStream.toByteArray()); 209 | // out.flush(); 210 | // out.close(); // flush and close 211 | // // Get Session ID 212 | // String key = ""; 213 | // if (connection != null) { 214 | // for (int i = 1; (key = connection.getHeaderFieldKey(i)) != null; i++) { 215 | // if (key.equalsIgnoreCase("set-cookie")) { 216 | // sessionId = connection.getHeaderField(key); 217 | // sessionId = sessionId.substring(0, sessionId.indexOf(";")); 218 | // } 219 | // } 220 | // } 221 | // } 222 | //} 223 | -------------------------------------------------------------------------------- /src/tools/FormHandler.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.BufferedReader; 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.io.UnsupportedEncodingException; 14 | import java.util.ArrayList; 15 | import java.util.HashMap; 16 | import java.util.Iterator; 17 | import java.util.Map; 18 | import java.util.Map.Entry; 19 | import java.util.Set; 20 | import java.util.StringTokenizer; 21 | 22 | import javax.xml.ws.spi.http.HttpExchange; 23 | 24 | public class FormHandler { 25 | // long logCnt; 26 | // 27 | // public FormHandler(long logCnt) { 28 | // this.logCnt = logCnt; 29 | // } 30 | // 31 | // public Map getFormData(HttpExchange xchg, String boundary, long fileSize) { 32 | // 33 | // Map params = parse(xchg); 34 | // return params; 35 | // } 36 | // 37 | //// public void responseForm(HttpExchange xchg, Coconut responseCoconut, String boundary) throws IOException { 38 | //// JSONObject responseJSON = null; 39 | //// 40 | //// responseJSON = responseCoconut.responseData(); 41 | //// 42 | //// Headers header = xchg.getResponseHeaders(); 43 | //// header.add("Content-Type", "application/json"); 44 | //// header.set("Access-Control-Allow-Origin", "*"); 45 | //// header.set("Access-Control-Allow-Headers", "X-Requested-With");// 46 | //// header.set("Access-Control-Allow-Methods", "POST"); 47 | //// 48 | //// xchg.sendResponseHeaders(200, responseJSON.toString().length()); 49 | //// 50 | //// OutputStream os = xchg.getResponseBody(); 51 | //// os.write(responseJSON.toString().getBytes("UTF-8")); 52 | //// os.flush(); 53 | //// os.close(); 54 | //// xchg.close(); 55 | //// 56 | //// System.out.println("\n-----------------------------------------------------------------------\n"); 57 | //// CoconutzLog.clear(logCnt); 58 | //// } 59 | // 60 | // private void readLine(InputStream is, ByteArrayOutputStream baos) throws IOException { 61 | // baos.reset(); 62 | // boolean preisr = false; 63 | // int d; 64 | // while ((d = is.read()) != -1) { 65 | // if (d == '\n' && preisr) { 66 | // return; 67 | // } 68 | // if (preisr) { 69 | // baos.write('\r'); 70 | // } 71 | // if (!(preisr = d == '\r')) { 72 | // baos.write(d); 73 | // } 74 | // } 75 | // if (preisr) { 76 | // baos.write('\r'); 77 | // } 78 | // } 79 | // 80 | // private int boundaryEqual(String boundary, ByteArrayOutputStream baos) throws IOException { 81 | // if (boundary.length() + 2 == baos.size()) { 82 | // if (("--" + boundary).equals(new String(baos.toByteArray(), "UTF-8"))) { 83 | // return 1; 84 | // } 85 | // } else if (boundary.length() + 4 == baos.size()) { 86 | // if (("--" + boundary + "--").equals(new String(baos.toByteArray(), "UTF-8"))) { 87 | // return 2; 88 | // } 89 | // } 90 | // return 0; 91 | // } 92 | // 93 | // private Map parse(HttpExchange httpExchange) { 94 | // try { 95 | // String contentType = httpExchange.getRequestHeaders().getFirst("Content-Type"); 96 | // HashMap map = new HashMap(); 97 | // if (httpExchange.getRequestMethod().equalsIgnoreCase("post") && contentType != null) { 98 | // String boundary = contentType.substring("multipart/form-data; boundary=".length()); 99 | // BufferedInputStream is = new BufferedInputStream(httpExchange.getRequestBody()); 100 | // ByteArrayOutputStream baos = new ByteArrayOutputStream(); 101 | // 102 | // readLine(is, baos); 103 | // int r = boundaryEqual(boundary, baos); 104 | // if (r != 1) 105 | // return map; 106 | // loop: while (true) { 107 | // String name = null; 108 | // String filename = null; 109 | // while (true) { 110 | // readLine(is, baos); 111 | // if (baos.size() == 0) 112 | // break; 113 | // String s = new String(baos.toByteArray(), "UTF-8"); 114 | // if (s.startsWith("Content-Disposition:")) { 115 | // for (String ss : s.split(";")) { 116 | // ss = ss.trim(); 117 | // if (ss.startsWith("name=")) { 118 | // name = ss.substring("name=".length() + 1, ss.length() - 1); 119 | // } else if (ss.startsWith("filename=")) { 120 | // filename = ss.substring("filename=".length() + 1, ss.length() - 1); 121 | // } 122 | // } 123 | // } 124 | // } 125 | // ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); 126 | // while (true) { 127 | // readLine(is, baos); 128 | // r = boundaryEqual(boundary, baos); 129 | // if (r == 0) { 130 | // baos.write(13); 131 | // baos.write(10); 132 | // baos2.write(baos.toByteArray()); 133 | // continue; 134 | // } 135 | // if (name != null) { 136 | // if (filename != null) { 137 | // Object files = map.get(name); 138 | // if (files == null) { 139 | // String time = "" + System.currentTimeMillis(); 140 | // filename = time + "/" + filename; 141 | // System.out.println(filename); 142 | // File file = new File(time); 143 | // file.mkdirs(); 144 | // FileOutputStream fos = new FileOutputStream(filename); 145 | // fos.write(baos2.toByteArray(), 0, baos2.toByteArray().length - 2); 146 | // fos.close(); 147 | // map.put(name, filename); 148 | // } 149 | // } else { 150 | // Object vals = map.get(name); 151 | // if (vals == null) { 152 | // byte[] b = baos2.toByteArray(); 153 | // byte[] b2 = new byte[baos2.size() - 2]; 154 | // for (int i = 0; i < baos2.size() - 2; i++) 155 | // b2[i] = b[i]; 156 | // map.put(name, new String(b2)); 157 | // } 158 | // } 159 | // } 160 | // if (r == 1) { 161 | // continue loop; 162 | // } else { 163 | // break loop; 164 | // } 165 | // } 166 | // } 167 | // } 168 | // return map; 169 | // } catch (IOException e) { 170 | //// CoconutzLog.put(logCnt, e.getMessage()); 171 | // e.printStackTrace(); 172 | // } 173 | // return null; 174 | // } 175 | // 176 | // public JSONObject toJson(Map inputForm) { 177 | // 178 | // JSONObject requestJSON = new JSONObject(); 179 | // JSONObject parameterJSON = new JSONObject(); 180 | // 181 | // Set> set = inputForm.entrySet(); 182 | // Iterator> it = set.iterator(); 183 | // try { 184 | // while (it.hasNext()) { 185 | // Entry entry = it.next(); 186 | // 187 | // String key = entry.getKey(); 188 | // String value = entry.getValue(); 189 | // // try { 190 | // // byte[] bb = entry.getValue().getBytes("8859_1"); 191 | // // String temp = new String(bb); 192 | // // String Result = new String( bb, "euc-kr" ); 193 | // // byte[] bb1 = entry.getValue().getBytes("EUC-KR"); 194 | // // String temp1 = new String(bb); 195 | // // String Result1 = new String( bb, "UTF-8" ); 196 | // // 197 | // // System.out.println(temp); 198 | // // System.out.println(temp1); 199 | // // System.out.println(Result); 200 | // // System.out.println(Result1); 201 | // // 202 | // // System.out.println(new String 203 | // // (entry.getValue().getBytes("UTF-8"), "KSC5601") ); 204 | // // System.out.println(new 205 | // // String(entry.getValue().getBytes("utf-8"), "euc-kr")); 206 | // // System.out.println(new 207 | // // String(entry.getValue().getBytes("utf-8"), "ksc5601")); 208 | // // System.out.println(new 209 | // // String(entry.getValue().getBytes("utf-8"), "x-windows-949")); 210 | // // System.out.println(new 211 | // // String(entry.getValue().getBytes("utf-8"), "iso-8859-1")); 212 | // // System.out.println(new 213 | // // String(entry.getValue().getBytes("iso-8859-1"), "euc-kr")); 214 | // // System.out.println(new 215 | // // String(entry.getValue().getBytes("iso-8859-1"), "ksc5601")); 216 | // // System.out.println(new 217 | // // String(entry.getValue().getBytes("iso-8859-1"), 218 | // // "x-windows-949")); 219 | // // System.out.println(new 220 | // // String(entry.getValue().getBytes("iso-8859-1"), "utf-8")); 221 | // // System.out.println(new 222 | // // String(entry.getValue().getBytes("euc-kr"), "ksc5601")); 223 | // // System.out.println(new 224 | // // String(entry.getValue().getBytes("euc-kr"), "utf-8")); 225 | // // System.out.println(new 226 | // // String(entry.getValue().getBytes("euc-kr"), 227 | // // "x-windows-949")); 228 | // // System.out.println(new 229 | // // String(entry.getValue().getBytes("euc-kr"), "iso-8859-1")); 230 | // // System.out.println(new 231 | // // String(entry.getValue().getBytes("ksc5601"), "euc-kr")); 232 | // // System.out.println(new 233 | // // String(entry.getValue().getBytes("ksc5601"), "utf-8")); 234 | // // System.out.println(new 235 | // // String(entry.getValue().getBytes("ksc5601"), 236 | // // "x-windows-949")); 237 | // // System.out.println(new 238 | // // String(entry.getValue().getBytes("ksc5601"), "iso-8859-1")); 239 | // // System.out.println(new 240 | // // String(entry.getValue().getBytes("x-windows-949"), 241 | // // "euc-kr")); 242 | // // System.out.println(new 243 | // // String(entry.getValue().getBytes("x-windows-949"), "utf-8")); 244 | // // System.out.println(new 245 | // // String(entry.getValue().getBytes("x-windows-949"), 246 | // // "ksc5601")); 247 | // // System.out.println(new 248 | // // String(entry.getValue().getBytes("x-windows-949"), 249 | // // "iso-8859-1")); 250 | // // } catch (UnsupportedEncodingException e) { 251 | // // // TODO Auto-generated catch block 252 | // // e.printStackTrace(); 253 | // // } 254 | // 255 | // if (key.equals("user") || key.equals("class") || key.equals("function") || key.equals("returntype")) { 256 | // 257 | // requestJSON.put(key, value); 258 | // } else { 259 | // parameterJSON.put(key, value); 260 | // } 261 | // 262 | // System.out.println("Key:" + entry.getKey() + "\tValue:" + value); 263 | // } 264 | // // System.out.println(requestJSON.toString()); 265 | // // System.out.println(parameterJSON.toString()); 266 | // 267 | // if (parameterJSON.length() != 0) { 268 | // requestJSON.put("parameter", parameterJSON); 269 | // } 270 | // } catch (JSONException e) { 271 | // CoconutzLog.put(logCnt, e.getMessage()); 272 | // } 273 | // return requestJSON; 274 | // } 275 | } 276 | -------------------------------------------------------------------------------- /src/JUnit/TestChangeGroup.java: -------------------------------------------------------------------------------- 1 | package JUnit; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | import java.net.UnknownHostException; 7 | 8 | import org.junit.Test; 9 | 10 | import protocol.ProtoHead; 11 | import protocol.Data.ChatData.ChatItem; 12 | import protocol.Data.GroupData.GroupItem; 13 | import protocol.Msg.ChangeGroupMsg.ChangeGroupReq; 14 | import protocol.Msg.ChangeGroupMsg.ChangeGroupReq.ChangeType; 15 | import protocol.Msg.ChangeGroupMsg.ChangeGroupRsp; 16 | import protocol.Msg.ChangeGroupMsg.ChangeGroupSync; 17 | import protocol.Msg.LoginMsg.LoginRsp; 18 | import protocol.Msg.LogoutMsg.LogoutRsp; 19 | import protocol.Msg.ReceiveChatMsg.ReceiveChatSync; 20 | import server.NetworkPacket; 21 | import tools.DataTypeTranslater; 22 | 23 | /** 24 | * 对“修改群聊用户”功能的测试 25 | * 26 | * @author Feng 27 | * 28 | */ 29 | public class TestChangeGroup { 30 | 31 | private ChangeGroupRsp sendRequest(ClientSocket clientSocket, ChangeGroupReq.Builder builder) throws IOException { 32 | clientSocket.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.CHANGE_GROUP_REQ_VALUE, builder.build() 33 | .toByteArray())); 34 | 35 | byte[] byteArray = clientSocket.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.CHANGE_GROUP_RSP); 36 | return ChangeGroupRsp.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 37 | } 38 | 39 | /** 40 | * 测试添加新用户(无权限) 41 | * 42 | * @author Feng 43 | * @throws IOException 44 | * @throws UnknownHostException 45 | */ 46 | // @Test 47 | public void addMember1() throws UnknownHostException, IOException { 48 | String groupId = "13"; 49 | ClientSocket clientSocket1 = new ClientSocket(); 50 | 51 | ChangeGroupReq.Builder builder = ChangeGroupReq.newBuilder(); 52 | builder.setChangeType(ChangeType.ADD); 53 | builder.setGroupId(groupId); 54 | builder.addUserId("d"); 55 | builder.addUserId("e"); 56 | 57 | // 无权限添加 58 | ChangeGroupRsp response = sendRequest(clientSocket1, builder); 59 | assertEquals(response.getResultCode(), ChangeGroupRsp.ResultCode.NO_AUTHORITY); 60 | 61 | clientSocket1.close(); 62 | } 63 | 64 | /** 65 | * 测试添加新用户(有权限,成功) 66 | * 67 | * @author Feng 68 | * @throws IOException 69 | * @throws UnknownHostException 70 | */ 71 | // @Test 72 | public void addMember2() throws UnknownHostException, IOException { 73 | String groupId = "13", user1 = "b", user2 = "c"; 74 | ClientSocket clientSocket1 = new ClientSocket(); 75 | ClientSocket clientSocket2 = new ClientSocket(); 76 | 77 | ChangeGroupReq.Builder builder = ChangeGroupReq.newBuilder(); 78 | builder.setChangeType(ChangeType.ADD); 79 | builder.setGroupId(groupId); 80 | builder.addUserId("d"); 81 | builder.addUserId("e"); 82 | 83 | // 登陆 84 | assertEquals(clientSocket1.login(user1, user1), LoginRsp.ResultCode.SUCCESS); 85 | assertEquals(clientSocket2.login(user2, user2), LoginRsp.ResultCode.SUCCESS); 86 | System.out.println(user1 + " , " + user2 + " Login Over!"); 87 | 88 | // 发送增加成员请求 89 | ChangeGroupRsp response = sendRequest(clientSocket1, builder); 90 | assertEquals(response.getResultCode(), ChangeGroupRsp.ResultCode.SUCCESS); 91 | 92 | // user1 接收同步数据(CHANGE_GROUP_SYNC)包 93 | byte[] byteArray = clientSocket1.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.CHANGE_GROUP_SYNC); 94 | assertNotNull(byteArray); 95 | ChangeGroupSync sync = ChangeGroupSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 96 | GroupItem groupItem = sync.getGroupItem(); 97 | // log 98 | System.out.println("CHANGE_GROUP_SYNC : " + user1 + " : " + ClientSocket.getGroupItemInfo(groupItem)); 99 | 100 | // user2上线收消息 101 | // 收取群数据更新 102 | byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.CHANGE_GROUP_SYNC); 103 | assertNotNull(byteArray); 104 | sync = ChangeGroupSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 105 | groupItem = sync.getGroupItem(); 106 | // log 107 | System.out.println("CHANGE_GROUP_SYNC : " + user2 + " : " + ClientSocket.getGroupItemInfo(groupItem)); 108 | 109 | byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 110 | ReceiveChatSync receiveChatting = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 111 | ChatItem chatItem2 = receiveChatting.getChatData(0); 112 | 113 | // 收到群聊消息(A 我已经把 B,C 拉入群聊) 114 | System.out.println("RECEIVE_CHAT_SYNC : " + user2 + " : " + ClientSocket.getChatItemInfo(chatItem2)); 115 | 116 | clientSocket1.close(); 117 | clientSocket2.close(); 118 | } 119 | 120 | /** 121 | * 测试删除群聊成员(无权限 122 | * 123 | * @throws UnknownHostException 124 | * @throws IOException 125 | * @author Feng 126 | */ 127 | // @Test 128 | public void deleteMember1() throws UnknownHostException, IOException { 129 | String groupId = "13"; 130 | ClientSocket clientSocket1 = new ClientSocket(); 131 | 132 | ChangeGroupReq.Builder builder = ChangeGroupReq.newBuilder(); 133 | builder.setChangeType(ChangeType.DELETE); 134 | builder.setGroupId(groupId); 135 | // builder.addUserId("d"); 136 | // builder.addUserId("e"); 137 | 138 | clientSocket1.writeToServer(NetworkPacket.packMessage(ProtoHead.ENetworkMessage.CHANGE_GROUP_REQ_VALUE, builder.build() 139 | .toByteArray())); 140 | 141 | // 未登录,无权限 142 | ChangeGroupRsp response = sendRequest(clientSocket1, builder); 143 | assertEquals(response.getResultCode(), ChangeGroupRsp.ResultCode.NO_AUTHORITY); 144 | System.out.println(response.getResultCode().toString()); 145 | 146 | clientSocket1.close(); 147 | } 148 | 149 | /** 150 | * 测试删除群聊成员 151 | * 152 | * @throws UnknownHostException 153 | * @throws IOException 154 | * @author Feng 155 | */ 156 | // @Test 157 | public void deleteMember2() throws UnknownHostException, IOException { 158 | String groupId = "13"; 159 | String user1 = "d", user2 = "a"; 160 | ClientSocket clientSocket1 = new ClientSocket(); 161 | ClientSocket clientSocket2 = new ClientSocket(); 162 | 163 | ChangeGroupReq.Builder builder = ChangeGroupReq.newBuilder(); 164 | builder.setChangeType(ChangeType.DELETE); 165 | builder.setGroupId(groupId); 166 | // builder.addUserId("d"); 167 | // builder.addUserId("e"); 168 | 169 | // 登陆 170 | assertEquals(clientSocket1.login(user1, user1), LoginRsp.ResultCode.SUCCESS); 171 | assertEquals(clientSocket2.login(user2, user2), LoginRsp.ResultCode.SUCCESS); 172 | System.out.println(user1 + " , " + user2 + " login"); 173 | 174 | // 请求自删 175 | ChangeGroupRsp response = sendRequest(clientSocket1, builder); 176 | assertEquals(response.getResultCode(), ChangeGroupRsp.ResultCode.SUCCESS); 177 | 178 | // user2上线收消息 179 | byte[] byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.CHANGE_GROUP_SYNC); 180 | assertNotNull(byteArray); 181 | ChangeGroupSync sync = ChangeGroupSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 182 | System.out.println("CHANGE_GROUP_SYNC : " + user2 + " : " + ClientSocket.getGroupItemInfo(sync.getGroupItem())); 183 | 184 | // 获取user1的系统退出消息 185 | byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 186 | assertNotNull(byteArray); 187 | ChatItem chatItem = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)).getChatData(0); 188 | System.out.println("CHANGE_GROUP_SYNC : " + user2 + " : " + ClientSocket.getChatItemInfo(chatItem)); 189 | 190 | clientSocket1.close(); 191 | clientSocket2.close(); 192 | } 193 | 194 | /** 195 | * 无权限修改群数据 196 | * 197 | * @author Feng 198 | * @throws IOException 199 | * @throws UnknownHostException 200 | */ 201 | // @Test 202 | public void reviseGroupInfo1() throws UnknownHostException, IOException { 203 | String groupId = "13"; 204 | ClientSocket clientSocket1 = new ClientSocket(); 205 | 206 | ChangeGroupReq.Builder builder = ChangeGroupReq.newBuilder(); 207 | builder.setChangeType(ChangeType.UPDATE_INFO); 208 | builder.setGroupId(groupId); 209 | builder.setGroupName("Fucking"); 210 | 211 | // 无权限添加 212 | ChangeGroupRsp response = sendRequest(clientSocket1, builder); 213 | assertEquals(response.getResultCode(), ChangeGroupRsp.ResultCode.NO_AUTHORITY); 214 | 215 | clientSocket1.close(); 216 | 217 | } 218 | 219 | /** 220 | * 有权限修改群数据 221 | * 222 | * @author Feng 223 | * @throws IOException 224 | * @throws UnknownHostException 225 | */ 226 | @Test 227 | public void reviseGroupInfo2() throws UnknownHostException, IOException { 228 | String groupId = "13"; 229 | String user1 = "a", user2 = "b"; 230 | ClientSocket clientSocket1 = new ClientSocket(); 231 | ClientSocket clientSocket2 = new ClientSocket(); 232 | 233 | ChangeGroupReq.Builder builder = ChangeGroupReq.newBuilder(); 234 | builder.setChangeType(ChangeType.UPDATE_INFO); 235 | builder.setGroupId(groupId); 236 | builder.setGroupName("Fucking"); 237 | 238 | // 登陆 239 | // assertEquals(clientSocket2.login(user1, user1), LoginRsp.ResultCode.SUCCESS); 240 | assertEquals(clientSocket1.login(user1, user1), LoginRsp.ResultCode.SUCCESS); 241 | assertEquals(clientSocket2.login(user2, user2), LoginRsp.ResultCode.SUCCESS); 242 | System.out.println(user1 + " , " + user2 + " login"); 243 | 244 | // 请求修改 245 | ChangeGroupRsp response = sendRequest(clientSocket1, builder); 246 | assertEquals(response.getResultCode(), ChangeGroupRsp.ResultCode.SUCCESS); 247 | System.out.println("请求完毕!"); 248 | 249 | // user1上线收同步数据包 250 | byte[] byteArray = clientSocket1.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.CHANGE_GROUP_SYNC); 251 | assertNotNull(byteArray); 252 | ChangeGroupSync sync = ChangeGroupSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 253 | System.out.println("CHANGE_GROUP_SYNC : " + user1 + " : " + ClientSocket.getGroupItemInfo(sync.getGroupItem())); 254 | 255 | // user2上线收同步数据包 256 | byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.CHANGE_GROUP_SYNC); 257 | assertNotNull(byteArray); 258 | sync = ChangeGroupSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)); 259 | System.out.println("CHANGE_GROUP_SYNC : " + user2 + " : " + ClientSocket.getGroupItemInfo(sync.getGroupItem())); 260 | 261 | // 获取系统消息 262 | byteArray = clientSocket2.readFromServerWithoutKeepAlive(ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC); 263 | assertNotNull(byteArray); 264 | ChatItem chatItem = ReceiveChatSync.parseFrom(NetworkPacket.getMessageObjectBytes(byteArray)).getChatData(0); 265 | System.out.println("CHANGE_GROUP_SYNC : " + user2 + " : " + ClientSocket.getChatItemInfo(chatItem)); 266 | 267 | clientSocket1.close(); 268 | clientSocket2.close(); 269 | 270 | } 271 | } 272 | --------------------------------------------------------------------------------