├── .gitignore
├── LICENSE
├── README.md
├── config.h
├── config.m4
├── example
├── server.php
└── www
│ ├── form.html
│ ├── index.html
│ ├── webim
│ ├── login.html
│ ├── main.html
│ └── resource
│ │ ├── css
│ │ ├── bootstrap.css
│ │ ├── bootstrap1.css
│ │ ├── chat.css
│ │ └── main.css
│ │ ├── img
│ │ ├── avatar1.jpg
│ │ ├── button.gif
│ │ ├── button.jpg
│ │ ├── button1.jpg
│ │ ├── button2.jpg
│ │ ├── default.jpg
│ │ ├── f1.png
│ │ └── face
│ │ │ ├── 1.gif
│ │ │ ├── 10.gif
│ │ │ ├── 11.gif
│ │ │ ├── 12.gif
│ │ │ ├── 13.gif
│ │ │ ├── 14.gif
│ │ │ ├── 15.gif
│ │ │ ├── 16.gif
│ │ │ ├── 17.gif
│ │ │ ├── 18.gif
│ │ │ ├── 19.gif
│ │ │ ├── 2.gif
│ │ │ ├── 3.gif
│ │ │ ├── 4.gif
│ │ │ ├── 5.gif
│ │ │ ├── 6.gif
│ │ │ ├── 7.gif
│ │ │ ├── 8.gif
│ │ │ └── 9.gif
│ │ └── js
│ │ ├── bootstrap.js
│ │ ├── chat.js
│ │ ├── jquery.js
│ │ └── jquery.json.js
│ ├── webqq
│ ├── css
│ │ └── style.css
│ ├── images
│ │ ├── QQ-ICON.png
│ │ ├── body-bg.jpg
│ │ ├── bot-menu
│ │ │ ├── 01.png
│ │ │ ├── 02.png
│ │ │ ├── 03.png
│ │ │ ├── 04.png
│ │ │ ├── 05.png
│ │ │ ├── 06.png
│ │ │ ├── 07.png
│ │ │ ├── 08.png
│ │ │ ├── 09.png
│ │ │ ├── 10.png
│ │ │ ├── 11.png
│ │ │ ├── 12.png
│ │ │ ├── 13.png
│ │ │ ├── 14.png
│ │ │ ├── 15.png
│ │ │ └── 16.png
│ │ ├── box-bg.jpg
│ │ ├── chat
│ │ │ ├── fa.png
│ │ │ ├── icon-00.png
│ │ │ ├── icon-01.png
│ │ │ ├── icon-02.png
│ │ │ ├── icon-03.png
│ │ │ ├── icon-04.png
│ │ │ ├── icon-05.png
│ │ │ ├── icon-06.png
│ │ │ ├── icon-07.png
│ │ │ ├── menu-01.png
│ │ │ ├── menu-02.png
│ │ │ ├── menu-03.png
│ │ │ ├── menu-04.png
│ │ │ ├── menu-05.png
│ │ │ ├── menu-06.png
│ │ │ ├── menu-07.png
│ │ │ ├── menu-08.png
│ │ │ ├── menu-09.png
│ │ │ ├── menu-10.png
│ │ │ ├── win.png
│ │ │ └── wins.png
│ │ ├── github.png
│ │ ├── head
│ │ │ ├── 1.jpg
│ │ │ ├── 10.jpg
│ │ │ ├── 11.jpg
│ │ │ ├── 12.jpg
│ │ │ ├── 13.jpg
│ │ │ ├── 14.jpg
│ │ │ ├── 15.jpg
│ │ │ ├── 16.jpg
│ │ │ ├── 17.jpg
│ │ │ ├── 18.jpg
│ │ │ ├── 19.jpg
│ │ │ ├── 2.jpg
│ │ │ ├── 20.jpg
│ │ │ ├── 3.jpg
│ │ │ ├── 4.jpg
│ │ │ ├── 5.jpg
│ │ │ ├── 6.jpg
│ │ │ ├── 7.jpg
│ │ │ ├── 8.jpg
│ │ │ └── 9.jpg
│ │ ├── icon-02-01.png
│ │ ├── icon-02-02.png
│ │ ├── icon-02-03.png
│ │ ├── icon-02-04.png
│ │ ├── login
│ │ │ ├── head.jpg
│ │ │ └── qq-login-bg.jpg
│ │ ├── lv.png
│ │ ├── qq-bg.jpg
│ │ ├── qq-top-01.png
│ │ ├── qq-top-02.png
│ │ ├── qq-top.png
│ │ ├── qq-xuan-jiao.png
│ │ ├── serch.png
│ │ ├── svip.png
│ │ ├── top-menu.png
│ │ ├── win-bg.png
│ │ ├── win.png
│ │ └── zai.png
│ ├── index.html
│ ├── js
│ │ ├── index.js
│ │ ├── jquery.cookie.js
│ │ ├── jquery.js
│ │ ├── jquery.json.js
│ │ ├── nicescroll.js
│ │ └── superslide.2.1.js
│ └── register.html
│ └── website
│ ├── css
│ ├── bootstrap-theme.min.css
│ └── bootstrap.min.css
│ ├── img
│ ├── qq.png
│ └── return-back.png
│ ├── index.html
│ └── js
│ ├── .jquery.min.js.swp
│ ├── bootstrap.min.js
│ └── jquery.min.js
├── include
├── appnet_dict.h
├── appnet_event.h
├── appnet_list.h
├── appnet_request.h
├── appnet_response.h
├── appnet_sds.h
├── appnet_server.h
├── appnet_socket.h
├── appnet_websocket.h
├── base64.h
├── config.h
├── mime_types.h
├── rbtree.h
├── ring_buffer.h
├── sha1.h
├── share_memory.h
└── zmalloc.h
├── php_appnet.c
├── php_appnet.h
├── php_appnet_server.c
└── src
├── appnet_dict.c
├── appnet_epoll.c
├── appnet_event.c
├── appnet_list.c
├── appnet_request.c
├── appnet_response.c
├── appnet_sds.c
├── appnet_select.c
├── appnet_server.c
├── appnet_socket.c
├── appnet_websocket.c
├── appnet_worker.c
├── base64.c
├── rbtree.c
├── ring_buffer.c
├── sha1.c
├── share_memory.c
├── test.c
└── zmalloc.c
/.gitignore:
--------------------------------------------------------------------------------
1 | # Object files
2 | *.o
3 | *.ko
4 | *.obj
5 | *.elf
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Libraries
12 | *.lib
13 | *.a
14 | *.la
15 | *.lo
16 |
17 | # Shared objects (inc. Windows DLLs)
18 | *.dll
19 | *.so
20 | *.so.*
21 | *.dylib
22 |
23 | # Executables
24 | *.exe
25 | *.out
26 | *.app
27 | *.i*86
28 | *.x86_64
29 | *.hex
30 | core
31 |
32 | /.deps
33 | /.libs/
34 | /Makefile
35 | /Makefile.fragments
36 | /Makefile.global
37 | /Makefile.objects
38 | /acinclude.m4
39 | /aclocal.m4
40 | /autom4te.cache/
41 | /build/
42 | /config.guess
43 | /config.h.in
44 | /config.log
45 | /config.nice
46 | /config.status
47 | /config.sub
48 | /configure
49 | /configure.in
50 | /install-sh
51 | /libtool
52 | /ltmain.sh
53 | /missing
54 | /mkinstalldirs
55 | /run-tests.php
56 |
57 | /.autotools
58 | /.cproject
59 | /.project
60 | /.settings/
61 |
62 | # Debug files
63 | *.dSYM/
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, lchb369
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # appnet介绍
2 | appnet是一个由C语言开发基于linux epoll的多线程+多进程的高性能异步网络库,可以同时支持TCP,HTTP和Websocket混合协议,目标是用php7+appnet快速构建高性能的长连接服务器。使其可广泛用于聊天系统,游戏服务器,消息通知服务器等实时通信场景。
3 | 
4 | ##其特点有
5 |
6 | - 高性能,核心用纯C语言开发,epoll异步非阻塞事件通知机制,单线程可支撑10万并发连接
7 | - 易用性,使用方式简单,并提供PHP7.0版本扩展,简单几步就可塔建一个功能齐全的长连接服务器,不再需要nginx,apache,php-fpm等。
8 | - 高并发,多线程异步网络IO,Per Thread One Loop并发模型,多个worker进程并行处理业务。
9 | - 多协议,可混合TCP协议,websocket协议和简单http协议与服务器通信。
10 | - 内存优化,进程间通信使用共享内存,兼容jemalloc和tcmalloc内存优化技术。
11 | - 缓冲区优化,采用redis的动态缓冲区,根据数据包大小自动扩充,有效避免内存浪费和缓冲区溢出,其内存预分配策略降低了内存分配次数。从而提高内存分配效率。
12 | - 异步任务,耗时的任务可以投递到单独的任务进程异步处理,工作进程无需等待。
13 |
14 |
15 | ##安装方法:
16 | 1,源码安装PHP7.0以上版本
2,下载扩展到任意目录appnet
3,执行如下指令:
>cd appnet
>/usr/local/php7/bin/phpize
>./configure --with-php-config=/usr/local/php7/bin/php-config
>make
>make install
17 | 启动服务器
18 | >php example/server.php
19 | TCP测试:
20 | >telnet 127.0.0.1 3011
21 | Http/Websocket测试:
22 | webqq:http://www.appnet.site/webqq/index.html
23 | 双击QQ图标打开登录框,随便输入帐号进入
24 |
25 | 完整示例参见:https://github.com/lchb369/appnet_php7/blob/master/example/server.php
26 | 更多介绍参见:https://github.com/lchb369/appnet_php7/wiki/appnet%E4%BB%8B%E7%BB%8D
27 | QQ交流群:379084776
28 |
--------------------------------------------------------------------------------
/config.h:
--------------------------------------------------------------------------------
1 | /* config.h. Generated from config.h.in by configure. */
2 | /* config.h.in. Generated from configure.in by autoheader. */
3 |
4 | /* Whether to build appnet as dynamic module */
5 | #define COMPILE_DL_APPNET 1
6 |
7 | /* Define to 1 if you have the header file. */
8 | #define HAVE_DLFCN_H 1
9 |
10 | /* Define to 1 if you have the header file. */
11 | #define HAVE_INTTYPES_H 1
12 |
13 | /* Define to 1 if you have the header file. */
14 | #define HAVE_MEMORY_H 1
15 |
16 | /* Define to 1 if you have the header file. */
17 | #define HAVE_STDINT_H 1
18 |
19 | /* Define to 1 if you have the header file. */
20 | #define HAVE_STDLIB_H 1
21 |
22 | /* Define to 1 if you have the header file. */
23 | #define HAVE_STRINGS_H 1
24 |
25 | /* Define to 1 if you have the header file. */
26 | #define HAVE_STRING_H 1
27 |
28 | /* Define to 1 if you have the header file. */
29 | #define HAVE_SYS_STAT_H 1
30 |
31 | /* Define to 1 if you have the header file. */
32 | #define HAVE_SYS_TYPES_H 1
33 |
34 | /* Define to 1 if you have the header file. */
35 | #define HAVE_UNISTD_H 1
36 |
37 | /* Define to 1 if your C compiler doesn't accept -c and -o together. */
38 | /* #undef NO_MINUS_C_MINUS_O */
39 |
40 | /* Define to the address where bug reports for this package should be sent. */
41 | #define PACKAGE_BUGREPORT ""
42 |
43 | /* Define to the full name of this package. */
44 | #define PACKAGE_NAME ""
45 |
46 | /* Define to the full name and version of this package. */
47 | #define PACKAGE_STRING ""
48 |
49 | /* Define to the one symbol short name of this package. */
50 | #define PACKAGE_TARNAME ""
51 |
52 | /* Define to the home page for this package. */
53 | #define PACKAGE_URL ""
54 |
55 | /* Define to the version of this package. */
56 | #define PACKAGE_VERSION ""
57 |
58 | /* Define to 1 if you have the ANSI C header files. */
59 | #define STDC_HEADERS 1
60 |
--------------------------------------------------------------------------------
/config.m4:
--------------------------------------------------------------------------------
1 | dnl $Id$
2 | dnl config.m4 for extension appnet
3 |
4 | dnl Comments in this file start with the string 'dnl'.
5 | dnl Remove where necessary. This file will not work
6 | dnl without editing.
7 |
8 | dnl If your extension references something external, use with:
9 |
10 | dnl PHP_ARG_WITH(appnet, for appnet support,
11 | dnl Make sure that the comment is aligned:
12 | dnl [ --with-appnet Include appnet support])
13 |
14 | dnl Otherwise use enable:
15 |
16 | PHP_ARG_ENABLE(appnet, whether to enable appnet support,
17 | dnl Make sure that the comment is aligned:
18 | [ --enable-appnet Enable appnet support])
19 |
20 | if test -z "$PHP_DEBUG" ; then
21 | AC_ARG_ENABLE(debug, [--enable-debug compile with debugging system], [PHP_DEBUG=$enableval],[PHP_DEBUG=no] )
22 | fi
23 |
24 | AC_MSG_CHECKING([if compiling with clang])
25 | AC_COMPILE_IFELSE([
26 | AC_LANG_PROGRAM([], [[
27 | #ifndef __clang__
28 | not clang
29 | #endif
30 | ]])],
31 | [CLANG=yes], [CLANG=no]
32 | )
33 | AC_MSG_RESULT([$CLANG])
34 |
35 | if test "$CLANG" = "yes"; then
36 | CFLAGS="$CFLAGS -std=gnu89"
37 | fi
38 |
39 | if test "$PHP_APPNET" != "no"; then
40 | dnl Write more examples of tests here...
41 | PHP_ADD_LIBRARY(pthread)
42 | dnl # --with-appnet -> check with-path
43 | dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
44 | dnl SEARCH_FOR="/include/appnet.h" # you most likely want to change this
45 | dnl if test -r $PHP_APPNET/$SEARCH_FOR; then # path given as parameter
46 | dnl APPNET_DIR=$PHP_APPNET
47 | dnl else # search default path list
48 | dnl AC_MSG_CHECKING([for appnet files in default path])
49 | dnl for i in $SEARCH_PATH ; do
50 | dnl if test -r $i/$SEARCH_FOR; then
51 | dnl APPNET_DIR=$i
52 | dnl AC_MSG_RESULT(found in $i)
53 | dnl fi
54 | dnl done
55 | dnl fi
56 | dnl
57 | dnl if test -z "$APPNET_DIR"; then
58 | dnl AC_MSG_RESULT([not found])
59 | dnl AC_MSG_ERROR([Please reinstall the appnet distribution])
60 | dnl fi
61 |
62 | dnl # --with-appnet -> add include path
63 | PHP_ADD_INCLUDE($APPNET_DIR/include)
64 |
65 | dnl # --with-appnet -> check for lib and symbol presence
66 | dnl LIBNAME=appnet # you may want to change this
67 | dnl LIBSYMBOL=appnet # you most likely want to change this
68 |
69 | dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
70 | dnl [
71 | dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $APPNET_DIR/$PHP_LIBDIR, APPNET_SHARED_LIBADD)
72 | dnl AC_DEFINE(HAVE_APPNETLIB,1,[ ])
73 | dnl ],[
74 | dnl AC_MSG_ERROR([wrong appnet lib version or lib not found])
75 | dnl ],[
76 | dnl -L$APPNET_DIR/$PHP_LIBDIR -lm
77 | dnl ])
78 | dnl
79 | dnl PHP_SUBST(APPNET_SHARED_LIBADD)
80 |
81 | CFLAGS="-Wall -pthread $CFLAGS"
82 | LDFLAGS="$LDFLAGS -lpthread"
83 |
84 | PHP_SUBST(APPNET_SHARED_LIBADD)
85 | PHP_ADD_LIBRARY(pthread, 1, APPNET_SHARED_LIBADD)
86 | app_source="src/appnet_server.c \
87 | src/appnet_epoll.c \
88 | src/appnet_socket.c \
89 | src/appnet_worker.c \
90 | src/appnet_event.c \
91 | src/zmalloc.c \
92 | src/appnet_sds.c \
93 | src/appnet_dict.c \
94 | src/appnet_list.c \
95 | src/appnet_request.c \
96 | src/sha1.c \
97 | src/base64.c \
98 | src/appnet_websocket.c \
99 | src/share_memory.c \
100 | src/appnet_response.c"
101 | PHP_NEW_EXTENSION(appnet, $app_source php_appnet.c php_appnet_server.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
102 | fi
103 |
--------------------------------------------------------------------------------
/example/server.php:
--------------------------------------------------------------------------------
1 | close( $fd );
50 | }
51 |
52 | }
53 |
54 | public static function getOnline( $serv , $fd , $msg )
55 | {
56 | $resMsg = array(
57 | 'cmd' => 'getOnline',
58 | );
59 | $list = self::getConnlist();
60 | foreach ( $list as $clid => $info )
61 | {
62 | $resMsg['list'][] = array(
63 | 'fd' => $clid,
64 | 'name' => $info['name'],
65 | 'avatar' => $info['avatar'],
66 | );
67 | }
68 | $serv->send( $fd , json_encode( $resMsg ) );
69 | }
70 |
71 |
72 | private static function setConnlist( $fd , $conn )
73 | {
74 | if( WORKER_NUM > 1 )
75 | {
76 | $list = apcu_fetch( "webchat_conn_list" );
77 | $list[$fd] = $conn;
78 | apcu_store( "webchat_conn_list" , $list );
79 | }
80 | else
81 | {
82 | self::$connections[$fd] = $conn;
83 | }
84 | }
85 |
86 |
87 | private static function delConnlist( $fd )
88 | {
89 | if( WORKER_NUM > 1 )
90 | {
91 | $list = apcu_fetch( "webchat_conn_list" );
92 | unset( $list[$fd] );
93 | apcu_store( "webchat_conn_list" , $list );
94 | }
95 | else
96 | {
97 | unset( self::$connections[$fd] );
98 | }
99 | }
100 |
101 |
102 | private static function getConnlist()
103 | {
104 | if( WORKER_NUM > 1 )
105 | {
106 | $list = apcu_fetch( "webchat_conn_list" );
107 | return $list;
108 | }
109 | return self::$connections;
110 | }
111 |
112 | public static function onLogin( $serv , $fd , $msg )
113 | {
114 | $list = self::getConnlist();
115 | if( $list )
116 | {
117 | foreach( $list as $connfd => $info )
118 | {
119 | if( $info['session_id'] == $msg['session_id'] && $fd != $connfd )
120 | {
121 | echo "login repeat by same brower";
122 | self::broadcastOffLine( $serv , $connfd );
123 | }
124 | }
125 | }
126 |
127 |
128 | self::setConnlist( $fd , array( 'name' => $msg['name'] , 'avatar' => $msg['avatar'] , 'session_id' => $msg['session_id'] ));
129 |
130 | $resMsg = array(
131 | 'cmd' => 'login',
132 | 'fd' => $fd,
133 | 'name' => $msg['name'],
134 | 'avatar' => $msg['avatar'],
135 | );
136 | $len = $serv->send( $fd , json_encode( $resMsg ) );
137 | self::broadcastNewUser( $serv , $fd , $msg , $resMsg );
138 | }
139 |
140 | public static function broadcastNewUser( $serv , $fd , $msg , $resMsg )
141 | {
142 | $resMsg['cmd'] = 'newUser';
143 | $loginMsg = array(
144 | 'cmd' => 'fromMsg',
145 | 'from' => 0,
146 | 'channal' => 0 ,
147 | 'data' => $msg['name']."上线鸟。。",
148 | );
149 |
150 | $list = self::getConnlist();
151 | //将上线消息发送给所有人
152 | foreach ( $list as $clid => $info )
153 | {
154 | if( $fd != $clid )
155 | {
156 | $serv->send( $clid , json_encode( $resMsg ) );
157 | $serv->send( $clid , json_encode( $loginMsg ) );
158 | }
159 | }
160 | }
161 |
162 | public static function broadcastOffLine( $serv , $fd )
163 | {
164 | $list = self::getConnlist();
165 | if(empty($list[$fd]))return;
166 |
167 | $resMsg = array(
168 | 'cmd' => 'offline',
169 | 'fd' => $fd,
170 | 'from' => 0,
171 | 'channal' => 0 ,
172 | 'data' => $list[$fd]['name'],
173 | );
174 |
175 | //将下线消息发送给所有人
176 | foreach ( $list as $clid => $info )
177 | {
178 | if( $fd != $clid )
179 | {
180 | $serv->send( $clid , json_encode( $resMsg ) );
181 | }
182 | }
183 | unset( $list[$fd] );
184 | self::delConnlist( $fd );
185 | }
186 |
187 | public static function onMessage( $serv , $fd , $msg )
188 | {
189 | $resMsg = $msg;
190 | $resMsg['cmd'] = 'fromMsg';
191 | //表示群发
192 | if( $msg['channal'] == 0 )
193 | {
194 |
195 | $list = self::getConnlist();
196 | foreach ( $list as $clid => $info )
197 | {
198 | $serv->send( $clid , json_encode( $resMsg ) );
199 | }
200 | }
201 | //表示私聊
202 | elseif ( $msg['channal'] == 1 )
203 | {
204 | $serv->send( $msg['to'] , json_encode( $resMsg ) );
205 | $serv->send( $msg['from'] , json_encode( $resMsg ) );
206 | }
207 | //$serv->close( $fd );
208 | }
209 | }
210 |
211 |
212 | function onTaskCallback( $server , $data , $taskid , $from )
213 | {
214 | $pid = posix_getpid();
215 | echo "onTaskCallback data=[{$data}],taskid=[{$taskid}],from=[{$from}],pid={$pid} \n";
216 | }
217 |
218 | function onConnect( $server , $fd )
219 | {
220 | $pid = posix_getpid();
221 | echo "\n\nNew Connect:{$fd} pid={$pid} \n";
222 | }
223 |
224 | //在worker进程中,表示回调,在task进程中表示请求
225 | function onTask( $server, $data , $taskid, $from )
226 | {
227 | $pid = posix_getpid();
228 | echo "onTask data=[{$data}],taskid=[{$taskid}],from=[{$from}],pid={$pid} \n";
229 | //sleep( 3 );
230 | $ret = array(
231 | 'status' => 'ok',
232 | 'data' => array( 'a' => "aaaa" ),
233 | );
234 | $server->taskCallback( json_encode( $ret ) , $taskid , $from );
235 | }
236 |
237 | function onRecv( $server , $fd , $buffer )
238 | {
239 | $header = $server->getHeader();
240 | $pid = posix_getpid();
241 | echo "RecvClient:[{$header['Protocol']}][{$buffer}][{$fd}],pid={$pid} \n";
242 |
243 | if( $header['Protocol'] == "WEBSOCKET" )
244 | {
245 | WebChat::onReceive( $server , $fd, $buffer );
246 | }
247 | elseif( $header['Protocol'] == "HTTP" )
248 | {
249 | if( $header['Uri'] == '/' )
250 | {
251 | /*redirct url,httpRedirect( $url , $status ),$status can be 301 or 302*/
252 | $server->httpRedirect( "/website/index.html" );
253 |
254 | /*response a error header code if you need*/
255 | //$server->httpRespCode( 403 );
256 | return;
257 | }
258 |
259 | $data = $buffer;
260 | $data .= microtime();
261 | echo "Response:[".$data."]\n";
262 |
263 | /*add async task to task worker process*/
264 | //$server->addAsynTask( $data , 1 );
265 | $server->setHeader( "Connection" , "keep-alive" );
266 | //ajax访问时,会有跨域问题
267 | $server->setHeader( "Access-Control-Allow-Origin" , "*" );
268 | $server->send( $fd , $data );
269 | }
270 | else
271 | {
272 | $server->send( $fd , $buffer );
273 | }
274 | };
275 |
276 | function onClose( $server , $fd )
277 | {
278 | echo "CloseClient:$fd \n";
279 | $header = $server->getHeader();
280 | if( $header['Protocol'] == "WEBSOCKET" )
281 | {
282 | WebChat::broadcastOffLine( $server , $fd );
283 | }
284 | };
285 |
286 | function onStart( $server )
287 | {
288 | $pid = posix_getpid();
289 | echo "On Worker Start!! pid={$pid} \n";
290 | //3000ms means 3second
291 | $server->timerAdd( 3000 , "flag or json data" );
292 | };
293 |
294 | //on worker shutdown,you must save data in last time.
295 | function onFinal( $server )
296 | {
297 | $pid = posix_getpid();
298 | echo "On Worker Final!! pid={$pid} \n";
299 | };
300 |
301 | function onTimer( $server , $timer_id , $flag )
302 | {
303 | $pid = posix_getpid();
304 | echo "onTimer:flag={$flag},pid={$pid},timer_id={$timer_id}...\n";
305 | //if do not remove it, it will be call this function forever
306 | $server->timerRemove( $timer_id );
307 | }
308 |
309 |
310 | //dl( "appnet.so");
311 | $server = new AppnetServer( "0.0.0.0" , 3011 );
312 | $ret = $server->listenHttp( 80 );
313 | $server->listenWebsocket( 3200 );
314 |
315 | $server->setOption( APPNET_OPT_DAEMON , 1);
316 | $server->setOption( APPNET_OPT_WORKER_NUM , WORKER_NUM );
317 | $server->setOption( APPNET_OPT_TASK_WORKER_NUM , 0 );
318 | $server->setOption( APPNET_OPT_REACTOR_NUM, 1 );
319 | $server->setOption( APPNET_OPT_MAX_CONNECTION , 10000 );
320 | $server->setOption( APPNET_HTTP_DOCS_ROOT , $_SERVER['PWD']."/example/www/" );
321 | $server->setOption( APPNET_HTTP_UPLOAD_DIR, "/home/upload/" );
322 | $server->setOption( APPNET_HTTP_404_PAGE , "404.html" );
323 | $server->setOption( APPNET_HTTP_50X_PAGE , "50x.html" );
324 | $server->setOption( APPNET_HTTP_KEEP_ALIVE , 1 );
325 |
326 | $server->addEventListener( APPNET_EVENT_CONNECT , "onConnect");
327 | $server->addEventListener( APPNET_EVENT_RECV , "onRecv");
328 | $server->addEventListener( APPNET_EVENT_CLOSE , "onClose");
329 | $server->addEventListener( APPNET_EVENT_START , "onStart");
330 | $server->addEventListener( APPNET_EVENT_FINAL , "onFinal");
331 | $server->addEventListener( APPNET_EVENT_TIMER , "onTimer");
332 | $server->addEventListener( APPNET_EVENT_TASK , "onTask");
333 | $server->addEventListener( APPNET_EVENT_TASK_CB , "onTaskCallback" );
334 | $server->run();
335 |
336 | $info = $server->getInfo();
337 |
338 |
339 | ?>
340 |
--------------------------------------------------------------------------------
/example/www/form.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | appnet示例
5 |
6 |
7 | appnet示例
8 | website
9 | http表单上传
10 | websocket聊天室
11 |
12 | 静态页面和资源直接从tcp层返回客户端,所以服务端不会收到静态资源请求
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/example/www/webim/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
37 |
72 |
73 |
89 |
90 |
--------------------------------------------------------------------------------
/example/www/webim/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | appnet websocket chatroom
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
60 |
64 |
65 |
66 |
67 |
68 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
113 |
114 |
115 |
116 |
117 |
118 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/example/www/webim/resource/css/chat.css:
--------------------------------------------------------------------------------
1 | body {
2 | }
3 |
4 |
5 | ul.dropdown-menu {
6 | min-width: 100px;
7 | }
8 |
9 | .login-box {
10 | padding: 50px 0;
11 | background-color: white;
12 | }
13 |
14 | div.container {
15 | width: 98%;
16 | }
17 |
18 | .c-sidebar-nav {
19 | padding: 9px 0;
20 | }
21 |
22 | #left-column {
23 | position:fixed;
24 | left: -10px;
25 | }
26 |
27 | #chat-column {
28 | position: fixed;
29 | background-color: whiteSmoke;
30 | left: 220px;
31 | overflow:auto;
32 | height:600px;
33 | }
34 |
35 | #right-column {
36 | position:fixed;
37 | right: 10px;
38 | }
39 |
40 | #input-box {
41 | position:fixed;
42 | bottom: 0px;
43 | left: 220px;
44 | height: 65px;
45 | background-color: #DDD;
46 | }
47 |
48 | .post-form{
49 | margin: 10px 10px;
50 | }
51 |
52 | .separator {
53 | border-bottom: 1px solid #222;
54 | }
55 |
56 | #chat-column ul{
57 | list-style-type: none;
58 | margin-left: 0px;
59 | }
60 |
61 | div.message-container{
62 | clear: both;
63 | position:relative;
64 | line-height: 20px;
65 | padding: 6px 10px;
66 | }
67 |
68 | div#chat-messages {
69 | overflow: auto;
70 | height:450px;
71 | }
72 |
73 | div.msg-time{
74 | position:absolute;
75 | top:7px;
76 | right:10px;
77 | font-size: 11px;
78 | color: #999;
79 | }
80 |
81 | div.message{
82 | margin-right:100px;
83 | }
84 |
85 | #chat-column .userpic{
86 | float:left;
87 | margin-right:5px;
88 | }
89 |
90 | li.user-online {
91 | margin-bottom: 5px;
92 | }
93 |
94 | li.user-online img {
95 | margin-right: 5px;
96 | }
97 |
98 | #group-column {
99 | left: 250px;
100 | position: fixed;
101 | }
102 |
103 | .chat-room{
104 | margin-bottom: 20px;
105 | }
106 | #left-userlist {
107 | margin-left: 10px;
108 | }
109 |
110 | #left-userlist li {
111 | float: left;
112 | height: 60px;
113 | list-style: none outside none;
114 | margin-top: 10px;
115 | width: 60px;
116 | margin-left: 0px;
117 | }
118 | #left-userlist li img{
119 | border-radius: 5px;
120 | }
121 |
122 | .chat_face {
123 | text-align:center;
124 | height:28px;
125 | line-height:28px;
126 | color:#333;
127 | cursor:pointer;
128 | overflow:hidden;
129 | display:inline-block;
130 | }
131 |
132 | .chat_face_hover {
133 | color:#f25000;
134 | height:28px;
135 | line-height:28px;
136 | overflow:hidden;
137 | }
138 |
139 | .show_face {
140 | background:#FFFFFF;
141 | border:#ccc 1px solid;
142 | width:600px;
143 | display:none;
144 | z-index:9999;
145 | }
146 | .show_face_hovers {
147 | display:block;
148 | position:absolute;
149 | }
150 |
151 | .face {
152 | width:30px;
153 | margin-right:1px;
154 | height:30px;
155 | line-height:30px;
156 | font-size:13px;
157 | text-align:center;
158 | background:#f6f6f6;
159 | vertical-align:top;
160 | margin-bottom:1px;
161 | display:inline-block;
162 | }
163 |
--------------------------------------------------------------------------------
/example/www/webim/resource/css/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | }
3 |
4 |
5 | ul.dropdown-menu {
6 | min-width: 100px;
7 | }
8 |
9 | .login-box {
10 | padding: 50px 0;
11 | background-color: white;
12 | }
13 |
14 | div.container {
15 | width: 98%;
16 | }
17 |
18 | .c-sidebar-nav {
19 | padding: 9px 0;
20 | }
21 |
22 | #left-column {
23 | position:fixed;
24 | left: -10px;
25 | }
26 |
27 | #chat-column {
28 | position: fixed;
29 | background-color: whiteSmoke;
30 | left: 220px;
31 | overflow:auto;
32 | height:600px;
33 | }
34 |
35 | #right-column {
36 | position:fixed;
37 | right: 10px;
38 | }
39 |
40 | #input-box {
41 | position:fixed;
42 | bottom: 0px;
43 | left: 220px;
44 | height: 65px;
45 | background-color: #DDD;
46 | }
47 |
48 | .post-form{
49 | margin: 10px 10px;
50 | }
51 |
52 | .separator {
53 | border-bottom: 1px solid #222;
54 | }
55 |
56 | #chat-column ul{
57 | list-style-type: none;
58 | margin-left: 0px;
59 | }
60 |
61 | div.message-container{
62 | clear: both;
63 | position:relative;
64 | line-height: 20px;
65 | padding: 6px 10px;
66 | }
67 |
68 | div#chat-messages {
69 | overflow: auto;
70 | height:600px;
71 | }
72 |
73 | div.msg-time{
74 | position:absolute;
75 | top:7px;
76 | right:10px;
77 | font-size: 11px;
78 | color: #999;
79 | }
80 |
81 | div.message{
82 | margin-right:100px;
83 | }
84 |
85 | #chat-column .userpic{
86 | float:left;
87 | margin-right:5px;
88 | }
89 |
90 | li.user-online {
91 | margin-bottom: 5px;
92 | }
93 |
94 | li.user-online img {
95 | margin-right: 5px;
96 | }
97 |
98 | #group-column {
99 | left: 250px;
100 | position: fixed;
101 | }
102 |
103 | .chat-room{
104 | margin-bottom: 20px;
105 | }
106 | #left-userlist {
107 | margin-left: 10px;
108 | }
109 |
110 | #left-userlist li {
111 | float: left;
112 | height: 60px;
113 | list-style: none outside none;
114 | margin-top: 10px;
115 | width: 60px;
116 | margin-left: 0px;
117 | }
118 | #left-userlist li img{
119 | border-radius: 5px;
120 | }
--------------------------------------------------------------------------------
/example/www/webim/resource/img/avatar1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/avatar1.jpg
--------------------------------------------------------------------------------
/example/www/webim/resource/img/button.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/button.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/button.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/button.jpg
--------------------------------------------------------------------------------
/example/www/webim/resource/img/button1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/button1.jpg
--------------------------------------------------------------------------------
/example/www/webim/resource/img/button2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/button2.jpg
--------------------------------------------------------------------------------
/example/www/webim/resource/img/default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/default.jpg
--------------------------------------------------------------------------------
/example/www/webim/resource/img/f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/f1.png
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/1.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/10.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/10.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/11.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/11.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/12.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/12.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/13.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/13.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/14.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/14.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/15.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/15.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/16.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/16.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/17.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/17.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/18.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/18.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/19.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/19.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/2.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/3.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/4.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/5.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/6.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/6.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/7.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/7.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/8.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/8.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/img/face/9.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uther518/appnet/461869b68b2cceb49e6aace8d1632da43cdda483/example/www/webim/resource/img/face/9.gif
--------------------------------------------------------------------------------
/example/www/webim/resource/js/chat.js:
--------------------------------------------------------------------------------
1 | var ws = {};
2 | var client_id = 0;
3 | var userlist = {};
4 | var GET = new Object();
5 | GET = getRequest();
6 |
7 | var ip = document.domain;
8 | var port = location.port;
9 |
10 | $(document).ready(
11 | function() {
12 | if ( window.WebSocket || window.MozWebSocket)
13 | {
14 | ws = new WebSocket( "ws://"+ip+":"+port );
15 | /**
16 | * 连接建立时触发
17 | */
18 | ws.onopen = function(e)
19 | {
20 | //必须的输入一个名称和一个图像才可以聊天
21 | if (GET['name'] == undefined || GET['avatar'] == undefined)
22 | {
23 | alert('非法请求');
24 | ws.close();
25 | return false;
26 | }
27 |
28 | //发送登录信息
29 |
30 | msg = new Object();
31 | msg.cmd = 'login';
32 | msg.name = GET['name'];
33 | msg.avatar = GET['avatar'];
34 | ws.send( $.toJSON( msg ));
35 | };
36 |
37 | //有消息到来时触发
38 | ws.onmessage = function( e )
39 | {
40 | var cmd = $.evalJSON( e.data ).cmd;
41 | if( cmd == 'login' )
42 | {
43 | client_id = $.evalJSON( e.data ).fd;
44 | //获取在线列表
45 | msg = new Object();
46 | msg.cmd = 'getOnline';
47 | ws.send( $.toJSON( msg ) );
48 |
49 | //alert( "收到消息了:"+e.data );
50 | }
51 | else if( cmd == 'getOnline' )
52 | {
53 | showOnlineList( e.data );
54 | }
55 | else if( cmd == 'newUser' )
56 | {
57 | showNewUser( e.data );
58 | }
59 | else if( cmd == 'fromMsg' )
60 | {
61 | showNewMsg( e.data );
62 | }
63 | else if( cmd == 'offline' )
64 | {
65 | var cid = $.evalJSON( e.data ).fd;
66 | delUser( cid );
67 | showNewMsg( e.data );
68 | }
69 | };
70 |
71 |
72 | /**
73 | * 连接关闭事件
74 | */
75 | ws.onclose = function(e)
76 | {
77 | if( confirm( "您已退出聊天室" ))
78 | {
79 | //alert('您已退出聊天室');
80 | location.href = 'login.html';
81 | }
82 | };
83 |
84 | /**
85 | * 异常事件
86 | */
87 | ws.onerror = function(e)
88 | {
89 | alert( "异常:"+e.data );
90 | console.log("onerror");
91 | };
92 |
93 | function selectUser(userid) {
94 | $('#userlist').val(userid);
95 | }
96 | }
97 | else
98 | {
99 | alert("您的浏览器不支持WebSocket,请使用Chrome/FireFox/Safari/IE10浏览器");
100 | }
101 | });
102 |
103 |
104 | document.onkeydown = function(e){
105 | var ev = document.all ? window.event : e;
106 | if(ev.keyCode==13)
107 | {
108 | sendMsg();
109 | }
110 | }
111 |
112 | /**
113 | * 显示所有在线列表
114 | * @param data
115 | */
116 | function showOnlineList( data )
117 | {
118 | var dataObj = $.evalJSON( data );
119 | var li = '';
120 | var option = "" ;
121 |
122 | for ( var i = 0; i < dataObj.list.length; i++ )
123 | {
124 | li = li+"" +
125 | "" + "
"
128 |
129 | userlist[dataObj.list[i].fd] = dataObj.list[i].name;
130 |
131 | if( dataObj.list[i].fd != client_id )
132 | {
133 | option = option + ""
135 | }
136 | }
137 | $('#left-userlist').html( li );
138 | $('#userlist').html( option );
139 | }
140 |
141 | /**
142 | * 当有一个新用户连接上来时
143 | * @param userid
144 | */
145 | function showNewUser( data )
146 | {
147 | var dataObj = $.evalJSON( data );
148 | if( !userlist[dataObj.fd] )
149 | {
150 | userlist[dataObj.fd] = dataObj.name;
151 | if ( dataObj.fd != client_id )
152 | {
153 | $('#userlist').append( "");
154 |
155 | }
156 |
157 | $('#left-userlist').append(
158 | "" +
159 | "" + "
");
162 |
163 | }
164 | }
165 |
166 | /**
167 | * 显示新消息
168 | */
169 | function showNewMsg( data )
170 | {
171 | var dataObj = $.evalJSON( data );
172 | var content = xssFilter( dataObj.data )
173 | var fromId = dataObj.from;
174 | var channal = dataObj.channal;
175 | content = parseXss( content );
176 | var said = '';
177 |
178 | $("#msg-template .msg-time").html(GetDateT());
179 | if (fromId == 0)
180 | {
181 | $("#msg-template .userpic").html("");
182 | $("#msg-template .content").html(
183 | "【系统】" + content);
184 | }
185 | else
186 | {
187 | var html = '';
188 | var to = dataObj.to;
189 | //如果说话的是我自己
190 | if( client_id == fromId )
191 | {
192 | if( channal == 0 )
193 | {
194 | said = '我对大家说:';
195 | }
196 | else if( channal == 1 )
197 | {
198 | said = "我悄悄的对"+userlist[to]+"说:";
199 | }
200 |
201 | html += ''+said+' ';
202 |
203 | }
204 | else
205 | {
206 | if( channal == 0 )
207 | {
208 | said = '对大家说:';
209 | }
210 | else if( channal == 1 )
211 | {
212 | said = "悄悄的对我说:";
213 | }
214 |
215 | html += '' + userlist[fromId] + said;
217 | html += ' '
218 | }
219 | html += content + '';
220 | $("#msg-template .content").html(html);
221 | }
222 | $("#chat-messages").append($("#msg-template").html());
223 | $('#chat-messages')[0].scrollTop = 1000000;
224 |
225 | }
226 |
227 | function xssFilter(val)
228 | {
229 | val = val.replace(/&/g, '&').replace(//g, '>').replace(/\x22/g, '"').replace(/\x27/g, ''');
230 | return val;
231 | }
232 |
233 | function parseXss( val )
234 | {
235 | val = val.replace( /#(\d*)/g, '
' );
236 | val = val.replace( '&' , '&' );
237 | return val;
238 | }
239 |
240 |
241 | function GetDateT() {
242 | var d;
243 | d = new Date();
244 | var h,i,s;
245 |
246 | h = d.getHours();
247 | i = d.getMinutes();
248 | s = d.getSeconds();
249 |
250 | h = ( h < 10 ) ? '0'+h : h;
251 | i = ( i < 10 ) ? '0'+i : i;
252 | s = ( s < 10 ) ? '0'+s : s;
253 | return h+":"+i+":"+s;
254 | }
255 |
256 | function getRequest()
257 | {
258 | var url = location.search; // 获取url中"?"符后的字串
259 | var theRequest = new Object();
260 | if (url.indexOf("?") != -1) {
261 | var str = url.substr(1);
262 |
263 | strs = str.split("&");
264 | for ( var i = 0; i < strs.length; i++) {
265 | var decodeParam = decodeURIComponent( strs[i] );
266 | var param = decodeParam.split( "=" );
267 | theRequest[param[0]] = param[1];
268 | }
269 |
270 | }
271 | return theRequest;
272 | }
273 |
274 | function selectUser(userid)
275 | {
276 | $('#userlist').val(userid);
277 | }
278 |
279 | function delUser( userid )
280 | {
281 | $('#user_' + userid).remove();
282 | $('#inroom_' + userid).remove();
283 | delete (userlist[userid]);
284 |
285 | }
286 |
287 | function sendMsg()
288 | {
289 | var content = $('#msg_content').val();
290 | content = content.replace(" ", " ");
291 | if( !content )
292 | {
293 | return false;
294 | }
295 |
296 | if( $('#userlist').val() == 0 )
297 | {
298 | var msg = new Object();
299 | msg.cmd = 'message';
300 | msg.from = client_id;
301 | msg.channal = 0;
302 | msg.data = content;
303 | ws.send( $.toJSON( msg ) );
304 | }
305 | else
306 | {
307 | var msg = new Object();
308 | msg.cmd = 'message';
309 | msg.from = client_id;
310 | msg.to = $('#userlist').val();
311 | msg.channal = 1;
312 | msg.data = content;
313 | ws.send( $.toJSON( msg ) );
314 | }
315 | $('#msg_content').val( "" );
316 | return false;
317 |
318 | }
319 |
320 |
321 | $(document).ready(function(){
322 | var a = '';
323 | for( var i = 1 ; i < 20 ; i++ )
324 | {
325 | a = a+'
';
326 | }
327 | $("#show_face").html( a );
328 | });
329 |
330 |
331 | (function($){
332 | $.fn.extend({
333 | insertAtCaret:function( myValue )
334 | {
335 | var $t=$(this)[0];
336 | if( document.selection )
337 | {
338 | this.focus();
339 | sel = document.selection.createRange();
340 | sel.text = myValue;
341 | this.focus();
342 | }
343 | else if( $t.selectionStart || $t.selectionStart == '0')
344 | {
345 |
346 | var startPos = $t.selectionStart;
347 | var endPos = $t.selectionEnd;
348 | var scrollTop = $t.scrollTop;
349 | $t.value = $t.value.substring(0, startPos) + myValue + $t.value.substring(endPos, $t.value.length);
350 | this.focus();
351 | $t.selectionStart = startPos + myValue.length;
352 | $t.selectionEnd = startPos + myValue.length;
353 | $t.scrollTop = scrollTop;
354 | }
355 | else
356 | {
357 |
358 | this.value += myValue;
359 | this.focus();
360 | }
361 | }
362 | })
363 | })(jQuery);
364 |
365 |
366 | function selectFace( id )
367 | {
368 | var img = '
';
369 | $( "#msg_content" ).insertAtCaret( "#"+id );
370 | closeChatFace();
371 | }
372 |
373 |
374 | function showChatFace()
375 | {
376 | $("#chat_face").attr( "class" ,"chat_face chat_face_hover");
377 | $("#show_face" ).attr( "class" ,"show_face show_face_hovers");
378 | }
379 |
380 | function closeChatFace()
381 | {
382 | $("#chat_face").attr( "class" ,"chat_face" );
383 | $("#show_face" ).attr( "class" ,"show_face");
384 | }
385 |
386 | function toggleFace()
387 | {
388 | $("#chat_face").toggleClass("chat_face_hover" );
389 | $("#show_face").toggleClass("show_face_hovers" );
390 | }
391 |
--------------------------------------------------------------------------------
/example/www/webim/resource/js/jquery.json.js:
--------------------------------------------------------------------------------
1 | /*! jQuery JSON plugin 2.4.0 | code.google.com/p/jquery-json */
2 | (function($){'use strict';var escape=/["\\\x00-\x1f\x7f-\x9f]/g,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},hasOwn=Object.prototype.hasOwnProperty;$.toJSON=typeof JSON==='object'&&JSON.stringify?JSON.stringify:function(o){if(o===null){return'null';}
3 | var pairs,k,name,val,type=$.type(o);if(type==='undefined'){return undefined;}
4 | if(type==='number'||type==='boolean'){return String(o);}
5 | if(type==='string'){return $.quoteString(o);}
6 | if(typeof o.toJSON==='function'){return $.toJSON(o.toJSON());}
7 | if(type==='date'){var month=o.getUTCMonth()+1,day=o.getUTCDate(),year=o.getUTCFullYear(),hours=o.getUTCHours(),minutes=o.getUTCMinutes(),seconds=o.getUTCSeconds(),milli=o.getUTCMilliseconds();if(month<10){month='0'+month;}
8 | if(day<10){day='0'+day;}
9 | if(hours<10){hours='0'+hours;}
10 | if(minutes<10){minutes='0'+minutes;}
11 | if(seconds<10){seconds='0'+seconds;}
12 | if(milli<100){milli='0'+milli;}
13 | if(milli<10){milli='0'+milli;}
14 | return'"'+year+'-'+month+'-'+day+'T'+
15 | hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
16 | pairs=[];if($.isArray(o)){for(k=0;k
2 |
3 |
4 | QQ Powered By Appnet
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 |
16 |
17 |
35 |
36 |
37 |
38 |
43 |
47 |
48 |
55 |
搜索:联系人、讨论组、群、企业
56 |
57 |
65 |
70 |
97 |
98 |
99 |
100 |
105 |
106 |
107 |
108 |
109 |
站在别人的雨季,淋湿自己空弹一出戏.....
110 |
111 |
122 |
123 |
124 |
125 |
126 | -
127 |
128 | 在么?找你有点事
129 |
130 |
131 |
132 |
133 |
145 |
146 |
147 | 发送(S)
148 | 关闭(C)
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |