日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

浅谈php中使用websocket

發布時間:2024/9/20 php 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈php中使用websocket 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在PHP中,開發者需要考慮的東西比較多,從socket的連接、建立、綁定、監聽等都需要開發者自己去操作完成,對于初學者來說,難度方面也挺大的,所以本文的思路如下:

1、socket協議的簡介

2、介紹client與server之間的連接原理

3、PHP中建立socket的過程講解

4、用一個聊天室作為實例詳細講解在PHP中如何使用socket

一、socket協議的簡介

  WebSocket是什么,有什么優點

  WebSocket是一個持久化的協議,這是相對于http非持久化來說的。

  舉個簡單的例子,http1.0的生命周期是以request作為界定的,也就是一個request,一個response,對于http來說,本次client與server的會話到此結束;而在http1.1中,稍微有所改進,即添加了keep-alive,也就是在一個http連接中可以進行多個request請求和多個response接受操作。然而在實時通信中,并沒有多大的作用,http只能由client發起請求,server才能返回信息,即server不能主動向client推送信息,無法滿足實時通信的要求。而WebSocket可以進行持久化連接,即client只需進行一次握手,成功后即可持續進行數據通信,值得關注的是WebSocket實現client與server之間全雙工通信,即server端有數據更新時可以主動推送給client端。

二、介紹client與server之間的socket連接原理

1、下面是一個演示client和server之間建立WebSocket連接時握手部分

  

?

2、client與server建立socket時握手的會話內容,即request與response

  a、client建立WebSocket時向服務器端請求的信息

  GET /chat HTTP/1.1
  Host: server.example.com
  Upgrade: websocket //告訴服務器現在發送的是WebSocket協議
  Connection: Upgrade
  Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== //是一個Base64 encode的值,這個是瀏覽器隨機生成的,用于驗證服務器端返回數據是否是WebSocket助理
  Sec-WebSocket-Protocol: chat, superchat
  Sec-WebSocket-Version: 13
  Origin: http://example.com

  b、服務器獲取到client請求的信息后,根據WebSocket協議對數據進行處理并返回,其中要對Sec-WebSocket-Key進行加密等操作

  HTTP/1.1 101 Switching Protocols
  Upgrade: websocket //依然是固定的,告訴客戶端即將升級的是Websocket協議,而不是mozillasocket,lurnarsocket或者shitsocket
  Connection: Upgrade
  Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= //這個則是經過服務器確認,并且加密過后的 Sec-WebSocket-Key,也就是client要求建立WebSocket驗證的憑證
  Sec-WebSocket-Protocol: chat

?

3、socket建立連接原理圖:

  

?

?

三、PHP中建立socket的過程講解

1、在PHP中,client與server之間建立socket通信,首先在PHP中創建socket并監聽端口信息,代碼如下:

1

2

3

4

5

6

7

8

//傳相應的IP與端口進行創建socket操作

function?WebSocket($address,$port){

????$server?= socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

????socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);//1表示接受所有的數據包

????socket_bind($server,?$address,?$port);

????socket_listen($server);

????return?$server;

}

2、設計一個循環掛起WebSocket通道,進行數據的接收、處理和發送

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

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

//對創建的socket循環進行監聽,處理數據

function?run(){

????//死循環,直到socket斷開

????while(true){

????????$changes=$this->sockets;

????????$write=NULL;

????????$except=NULL;

?????????

????????/*

????????//這個函數是同時接受多個連接的關鍵,我的理解它是為了阻塞程序繼續往下執行。

????????socket_select ($sockets, $write = NULL, $except = NULL, NULL);

?

????????$sockets可以理解為一個數組,這個數組中存放的是文件描述符。當它有變化(就是有新消息到或者有客戶端連接/斷開)時,socket_select函數才會返回,繼續往下執行。

????????$write是監聽是否有客戶端寫數據,傳入NULL是不關心是否有寫變化。

????????$except是$sockets里面要被排除的元素,傳入NULL是”監聽”全部。

????????最后一個參數是超時時間

????????如果為0:則立即結束

????????如果為n>1: 則最多在n秒后結束,如遇某一個連接有新動態,則提前返回

????????如果為null:如遇某一個連接有新動態,則返回

????????*/

????????socket_select($changes,$write,$except,NULL);

????????foreach($changes?as?$sock){

?????????????

????????????//如果有新的client連接進來,則

????????????if($sock==$this->master){

?

????????????????//接受一個socket連接

????????????????$client=socket_accept($this->master);

?

????????????????//給新連接進來的socket一個唯一的ID

????????????????$key=uniqid();

????????????????$this->sockets[]=$client;??//將新連接進來的socket存進連接池

????????????????$this->users[$key]=array(

????????????????????'socket'=>$client,??//記錄新連接進來client的socket信息

????????????????????'shou'=>false???????//標志該socket資源沒有完成握手

????????????????);

????????????//否則1.為client斷開socket連接,2.client發送信息

????????????}else{

????????????????$len=0;

????????????????$buffer='';

????????????????//讀取該socket的信息,注意:第二個參數是引用傳參即接收數據,第三個參數是接收數據的長度

????????????????do{

????????????????????$l=socket_recv($sock,$buf,1000,0);

????????????????????$len+=$l;

????????????????????$buffer.=$buf;

????????????????}while($l==1000);

?

????????????????//根據socket在user池里面查找相應的$k,即健ID

????????????????$k=$this->search($sock);

?

????????????????//如果接收的信息長度小于7,則該client的socket為斷開連接

????????????????if($len<7){

????????????????????//給該client的socket進行斷開操作,并在$this->sockets和$this->users里面進行刪除

????????????????????$this->send2($k);

????????????????????continue;

????????????????}

????????????????//判斷該socket是否已經握手

????????????????if(!$this->users[$k]['shou']){

????????????????????//如果沒有握手,則進行握手處理

????????????????????$this->woshou($k,$buffer);

????????????????}else{

????????????????????//走到這里就是該client發送信息了,對接受到的信息進行uncode處理

????????????????????$buffer?=?$this->uncode($buffer,$k);

????????????????????if($buffer==false){

????????????????????????continue;

????????????????????}

????????????????????//如果不為空,則進行消息推送操作

????????????????????$this->send($k,$buffer);

????????????????}

????????????}

????????}

?????????

????}

?????

}

3、以上服務器端完成的WebSocket的前期工作后,就等著client連接進行,client創建WebSocket很簡單,代碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

var?ws =?new?WebSocket("ws://IP:端口");

//握手監聽函數

ws.onopen=function(){

?????//狀態為1證明握手成功,然后把client自定義的名字發送過去

????if(so.readyState==1){

?????????//握手成功后對服務器發送信息

?????so.send('type=add&ming='+n);

????}

}

//錯誤返回信息函數

ws.onerror =?function(){

????console.log("error");

};

//監聽服務器端推送的消息

ws.onmessage =?function?(msg){

????console.log(msg);

}

?

//斷開WebSocket連接

ws.onclose =?function(){

????ws = false;

}

四、聊天室實例代碼

1、PHP部分

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

39

40

41

42

43

44

45

46

47

48

49

50

51

52

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

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

<?php

error_reporting(E_ALL ^ E_NOTICE);

ob_implicit_flush();

?

//地址與接口,即創建socket時需要服務器的IP和端口

$sk=new?Sock('127.0.0.1',8000);

?

//對創建的socket循環進行監聽,處理數據

$sk->run();

?

//下面是sock類

class?Sock{

????public?$sockets;?//socket的連接池,即client連接進來的socket標志

????public?$users;???//所有client連接進來的信息,包括socket、client名字等

????public?$master;??//socket的resource,即前期初始化socket時返回的socket資源

?????

????private?$sda=array();???//已接收的數據

????private?$slen=array();??//數據總長度

????private?$sjen=array();??//接收數據的長度

????private?$ar=array();????//加密key

????private?$n=array();

?????

????public?function?__construct($address,?$port){

?

????????//創建socket并把保存socket資源在$this->master

????????$this->master=$this->WebSocket($address,?$port);

?

????????//創建socket連接池

????????$this->sockets=array($this->master);

????}

?????

????//對創建的socket循環進行監聽,處理數據

????function?run(){

????????//死循環,直到socket斷開

????????while(true){

????????????$changes=$this->sockets;

????????????$write=NULL;

????????????$except=NULL;

?????????????

????????????/*

????????????//這個函數是同時接受多個連接的關鍵,我的理解它是為了阻塞程序繼續往下執行。

????????????socket_select ($sockets, $write = NULL, $except = NULL, NULL);

?

????????????$sockets可以理解為一個數組,這個數組中存放的是文件描述符。當它有變化(就是有新消息到或者有客戶端連接/斷開)時,socket_select函數才會返回,繼續往下執行。

????????????$write是監聽是否有客戶端寫數據,傳入NULL是不關心是否有寫變化。

????????????$except是$sockets里面要被排除的元素,傳入NULL是”監聽”全部。

????????????最后一個參數是超時時間

????????????如果為0:則立即結束

????????????如果為n>1: 則最多在n秒后結束,如遇某一個連接有新動態,則提前返回

????????????如果為null:如遇某一個連接有新動態,則返回

????????????*/

????????????socket_select($changes,$write,$except,NULL);

????????????foreach($changes?as?$sock){

?????????????????

????????????????//如果有新的client連接進來,則

????????????????if($sock==$this->master){

?

????????????????????//接受一個socket連接

????????????????????$client=socket_accept($this->master);

?

????????????????????//給新連接進來的socket一個唯一的ID

????????????????????$key=uniqid();

????????????????????$this->sockets[]=$client;??//將新連接進來的socket存進連接池

????????????????????$this->users[$key]=array(

????????????????????????'socket'=>$client,??//記錄新連接進來client的socket信息

????????????????????????'shou'=>false???????//標志該socket資源沒有完成握手

????????????????????);

????????????????//否則1.為client斷開socket連接,2.client發送信息

????????????????}else{

????????????????????$len=0;

????????????????????$buffer='';

????????????????????//讀取該socket的信息,注意:第二個參數是引用傳參即接收數據,第三個參數是接收數據的長度

????????????????????do{

????????????????????????$l=socket_recv($sock,$buf,1000,0);

????????????????????????$len+=$l;

????????????????????????$buffer.=$buf;

????????????????????}while($l==1000);

?

????????????????????//根據socket在user池里面查找相應的$k,即健ID

????????????????????$k=$this->search($sock);

?

????????????????????//如果接收的信息長度小于7,則該client的socket為斷開連接

????????????????????if($len<7){

????????????????????????//給該client的socket進行斷開操作,并在$this->sockets和$this->users里面進行刪除

????????????????????????$this->send2($k);

????????????????????????continue;

????????????????????}

????????????????????//判斷該socket是否已經握手

????????????????????if(!$this->users[$k]['shou']){

????????????????????????//如果沒有握手,則進行握手處理

????????????????????????$this->woshou($k,$buffer);

????????????????????}else{

????????????????????????//走到這里就是該client發送信息了,對接受到的信息進行uncode處理

????????????????????????$buffer?=?$this->uncode($buffer,$k);

????????????????????????if($buffer==false){

????????????????????????????continue;

????????????????????????}

????????????????????????//如果不為空,則進行消息推送操作

????????????????????????$this->send($k,$buffer);

????????????????????}

????????????????}

????????????}

?????????????

????????}

?????????

????}

?????

????//指定關閉$k對應的socket

????function?close($k){

????????//斷開相應socket

????????socket_close($this->users[$k]['socket']);

????????//刪除相應的user信息

????????unset($this->users[$k]);

????????//重新定義sockets連接池

????????$this->sockets=array($this->master);

????????foreach($this->users?as?$v){

????????????$this->sockets[]=$v['socket'];

????????}

????????//輸出日志

????????$this->e("key:$k close");

????}

?????

????//根據sock在users里面查找相應的$k

????function?search($sock){

????????foreach?($this->users?as?$k=>$v){

????????????if($sock==$v['socket'])

????????????return?$k;

????????}

????????return?false;

????}

?????

????//傳相應的IP與端口進行創建socket操作

????function?WebSocket($address,$port){

????????$server?= socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

????????socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);//1表示接受所有的數據包

????????socket_bind($server,?$address,?$port);

????????socket_listen($server);

????????$this->e('Server Started : '.date('Y-m-d H:i:s'));

????????$this->e('Listening on?? : '.$address.' port '.$port);

????????return?$server;

????}

?????

?????

????/*

????* 函數說明:對client的請求進行回應,即握手操作

????* @$k clien的socket對應的健,即每個用戶有唯一$k并對應socket

????* @$buffer 接收client請求的所有信息

????*/

????function?woshou($k,$buffer){

?

????????//截取Sec-WebSocket-Key的值并加密,其中$key后面的一部分258EAFA5-E914-47DA-95CA-C5AB0DC85B11字符串應該是固定的

????????$buf??=?substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);

????????$key??= trim(substr($buf,0,strpos($buf,"\r\n")));

????????$new_key?=?base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));

?????????

????????//按照協議組合信息進行返回

????????$new_message?=?"HTTP/1.1 101 Switching Protocols\r\n";

????????$new_message?.=?"Upgrade: websocket\r\n";

????????$new_message?.=?"Sec-WebSocket-Version: 13\r\n";

????????$new_message?.=?"Connection: Upgrade\r\n";

????????$new_message?.=?"Sec-WebSocket-Accept: "?.?$new_key?.?"\r\n\r\n";

????????socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));

?

????????//對已經握手的client做標志

????????$this->users[$k]['shou']=true;

????????return?true;

?????????

????}

?????

????//解碼函數

????function?uncode($str,$key){

????????$mask?=?array();?

????????$data?=?'';?

????????$msg?= unpack('H*',$str);

????????$head?=?substr($msg[1],0,2);?

????????if?($head?==?'81'?&& !isset($this->slen[$key])) {?

????????????$len=substr($msg[1],2,2);

????????????$len=hexdec($len);//把十六進制的轉換為十進制

????????????if(substr($msg[1],2,2)=='fe'){

????????????????$len=substr($msg[1],4,4);

????????????????$len=hexdec($len);

????????????????$msg[1]=substr($msg[1],4);

????????????}else?if(substr($msg[1],2,2)=='ff'){

????????????????$len=substr($msg[1],4,16);

????????????????$len=hexdec($len);

????????????????$msg[1]=substr($msg[1],16);

????????????}

????????????$mask[] = hexdec(substr($msg[1],4,2));?

????????????$mask[] = hexdec(substr($msg[1],6,2));?

????????????$mask[] = hexdec(substr($msg[1],8,2));?

????????????$mask[] = hexdec(substr($msg[1],10,2));

????????????$s?= 12;

????????????$n=0;

????????}else?if($this->slen[$key] > 0){

????????????$len=$this->slen[$key];

????????????$mask=$this->ar[$key];

????????????$n=$this->n[$key];

????????????$s?= 0;

????????}

?????????

????????$e?=?strlen($msg[1])-2;

????????for?($i=$s;?$i<=?$e;?$i+= 2) {?

????????????$data?.=?chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));?

????????????$n++;?

????????}?

????????$dlen=strlen($data);

?????????

????????if($len?> 255 &&?$len?>?$dlen+intval($this->sjen[$key])){

????????????$this->ar[$key]=$mask;

????????????$this->slen[$key]=$len;

????????????$this->sjen[$key]=$dlen+intval($this->sjen[$key]);

????????????$this->sda[$key]=$this->sda[$key].$data;

????????????$this->n[$key]=$n;

????????????return?false;

????????}else{

????????????unset($this->ar[$key],$this->slen[$key],$this->sjen[$key],$this->n[$key]);

????????????$data=$this->sda[$key].$data;

????????????unset($this->sda[$key]);

????????????return?$data;

????????}

?????????

????}

?????

????//與uncode相對

????function?code($msg){

????????$frame?=?array();?

????????$frame[0] =?'81';?

????????$len?=?strlen($msg);

????????if($len?< 126){

????????????$frame[1] =?$len<16?'0'.dechex($len):dechex($len);

????????}else?if($len?< 65025){

????????????$s=dechex($len);

????????????$frame[1]='7e'.str_repeat('0',4-strlen($s)).$s;

????????}else{

????????????$s=dechex($len);

????????????$frame[1]='7f'.str_repeat('0',16-strlen($s)).$s;

????????}

????????$frame[2] =?$this->ord_hex($msg);

????????$data?= implode('',$frame);?

????????return?pack("H*",?$data);?

????}

?????

????function?ord_hex($data)? {?

????????$msg?=?'';?

????????$l?=?strlen($data);?

????????for?($i= 0;?$i<$l;?$i++) {?

????????????$msg?.=?dechex(ord($data{$i}));?

????????}?

????????return?$msg;?

????}

?????

????//用戶加入或client發送信息

????function?send($k,$msg){

????????//將查詢字符串解析到第二個參數變量中,以數組的形式保存如:parse_str("name=Bill&age=60",$arr)

????????parse_str($msg,$g);

????????$ar=array();

?

????????if($g['type']=='add'){

????????????//第一次進入添加聊天名字,把姓名保存在相應的users里面

????????????$this->users[$k]['name']=$g['ming'];

????????????$ar['type']='add';

????????????$ar['name']=$g['ming'];

????????????$key='all';

????????}else{

????????????//發送信息行為,其中$g['key']表示面對大家還是個人,是前段傳過來的信息

????????????$ar['nrong']=$g['nr'];

????????????$key=$g['key'];

????????}

????????//推送信息

????????$this->send1($k,$ar,$key);

????}

?????

????//對新加入的client推送已經在線的client

????function?getusers(){

????????$ar=array();

????????foreach($this->users?as?$k=>$v){

????????????$ar[]=array('code'=>$k,'name'=>$v['name']);

????????}

????????return?$ar;

????}

?????

????//$k 發信息人的socketID $key接受人的 socketID ,根據這個socketID可以查找相應的client進行消息推送,即指定client進行發送

????function?send1($k,$ar,$key='all'){

????????$ar['code1']=$key;

????????$ar['code']=$k;

????????$ar['time']=date('m-d H:i:s');

????????//對發送信息進行編碼處理

????????$str?=?$this->code(json_encode($ar));

????????//面對大家即所有在線者發送信息

????????if($key=='all'){

????????????$users=$this->users;

????????????//如果是add表示新加的client

????????????if($ar['type']=='add'){

????????????????$ar['type']='madd';

????????????????$ar['users']=$this->getusers();????????//取出所有在線者,用于顯示在在線用戶列表中

????????????????$str1?=?$this->code(json_encode($ar));?//單獨對新client進行編碼處理,數據不一樣

????????????????//對新client自己單獨發送,因為有些數據是不一樣的

????????????????socket_write($users[$k]['socket'],$str1,strlen($str1));

????????????????//上面已經對client自己單獨發送的,后面就無需再次發送,故unset

????????????????unset($users[$k]);

????????????}

????????????//除了新client外,對其他client進行發送信息。數據量大時,就要考慮延時等問題了

????????????foreach($users?as?$v){

????????????????socket_write($v['socket'],$str,strlen($str));

????????????}

????????}else{

????????????//單獨對個人發送信息,即雙方聊天

????????????socket_write($this->users[$k]['socket'],$str,strlen($str));

????????????socket_write($this->users[$key]['socket'],$str,strlen($str));

????????}

????}

?????

????//用戶退出向所用client推送信息

????function?send2($k){

????????$this->close($k);

????????$ar['type']='rmove';

????????$ar['nrong']=$k;

????????$this->send1(false,$ar,'all');

????}

?????

????//記錄日志

????function?e($str){

????????//$path=dirname(__FILE__).'/log.txt';

????????$str=$str."\n";

????????//error_log($str,3,$path);

????????//編碼處理

????????echo?iconv('utf-8','gbk//IGNORE',$str);

????}

}

?>

  

2、client部分

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

39

40

41

42

43

44

45

46

47

48

49

50

51

52

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

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<meta name="viewport"?content="width=device-width, initial-scale=1, user-scalable=no"/>

<title>HTML5 websocket 網頁聊天室 javascript php</title>

<style type="text/css">

body,p{margin:0px; padding:0px; font-size:14px; color:#333; font-family:Arial, Helvetica, sans-serif;}

#ltian,.rin{width:98%; margin:5px auto;}

#ltian{border:1px #ccc solid;overflow-y:auto; overflow-x:hidden; position:relative;}

#ct{margin-right:111px; height:100%;overflow-y:auto;overflow-x: hidden;}

#us{width:110px; overflow-y:auto; overflow-x:hidden; float:right; border-left:1px #ccc solid; height:100%; background-color:#F1F1F1;}

#us p{padding:3px 5px; color:#08C; line-height:20px; height:20px; cursor:pointer; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}

#us p:hover,#us p:active,#us p.ck{background-color:#069; color:#FFF;}

#us p.my:hover,#us p.my:active,#us p.my{color:#333;background-color:transparent;}

button{float:right; width:80px; height:35px; font-size:18px;}

input{width:100%; height:30px; padding:2px; line-height:20px; outline:none; border:solid 1px #CCC;}

.rin p{margin-right:160px;}

.rin span{float:right; padding:6px 5px 0px 5px; position:relative;}

.rin span img{margin:0px 3px; cursor:pointer;}

.rin span form{position:absolute; width:25px; height:25px; overflow:hidden; opacity:0; top:5px; right:5px;}

.rin span input{width:180px; height:25px; margin-left:-160px; cursor:pointer}

?

#ct p{padding:5px; line-height:20px;}

#ct a{color:#069; cursor:pointer;}

#ct span{color:#999; margin-right:10px;}

.c2{color:#999;}

.c3{background-color:#DBE9EC; padding:5px;}

.qp{position:absolute; font-size:12px; color:#666; top:5px; right:130px; text-decoration:none; color:#069;}

#ems{position:absolute; z-index:5; display:none; top:0px; left:0px; max-width:230px; background-color:#F1F1F1; border:solid 1px #CCC; padding:5px;}

#ems img{width:44px; height:44px; border:solid 1px #FFF; cursor:pointer;}

#ems img:hover,#ems img:active{border-color:#A4B7E3;}

#ems a{color:#069; border-radius:2px; display:inline-block; margin:2px 5px; padding:1px 8px; text-decoration:none; background-color:#D5DFFD;}

#ems a:hover,#ems a:active,#ems a.ck{color:#FFF; background-color:#069;}

.tc{text-align:center; margin-top:5px;}

</style>

</head>

?

<body>

<div id="ltian">

????<div id="us"?class="jb"></div>

????<div id="ct"></div>

????<a href="javascript:;"?class="qp"?onClick="this.parentNode.children[1].innerHTML=''">清屏</a>

</div>

<div?class="rin">

????<button id="sd">發送</button>

????<span><img src="http://www.yxsss.com/ui/sk/t.png"?title="表情"?id="imgbq"><img src="http://www.yxsss.com/ui/sk/e.png"?title="上傳圖片"><form><input type="file"?title="上傳圖片"?id="upimg"></form></span>

????<p><input id="nrong"></p>

</div>

<div id="ems"><p></p><p?class="tc"></p></div>

<script>

if(typeof(WebSocket)=='undefined'){

????alert('你的瀏覽器不支持 WebSocket ,推薦使用Google Chrome 或者 Mozilla Firefox');?

}

</script>

<script src="http://www.yxsss.com/ui/p/a.js"?type="text/javascript"></script>

<script>

(function(){

????var?key='all',mkey;

????var?users={};

????var?url='ws://127.0.0.1:8000';

????var?so=false,n=false;

????var?lus=A.$('us'),lct=A.$('ct');

????function?st(){

????????n=prompt('請給自己取一個響亮的名字:');

????????n=n.substr(0,16);

????????if(!n){

????????????return?;???

????????}

????????//創建socket,注意URL的格式:ws://ip:端口

????????so=new?WebSocket(url);

????????//握手監聽函數

????????so.onopen=function(){

????????????//狀態為1證明握手成功,然后把client自定義的名字發送過去

????????????if(so.readyState==1){

????????????????so.send('type=add&ming='+n);

????????????}

????????}

?????????

????????//握手失敗或者其他原因連接socket失敗,則清除so對象并做相應提示操作

????????so.onclose=function(){

????????????so=false;

????????????lct.appendChild(A.$$('<p class="c2">退出聊天室</p>'));

????????}

?????????

????????//數據接收監聽,接收服務器推送過來的信息,返回的數據給msg,然后進行顯示

????????so.onmessage=function(msg){

????????????eval('var da='+msg.data);

????????????var?obj=false,c=false;

????????????if(da.type=='add'){

????????????????var?obj=A.$$('<p>'+da.name+'</p>');

????????????????lus.appendChild(obj);

????????????????cuser(obj,da.code);

????????????????obj=A.$$('<p><span>['+da.time+']</span>歡迎<a>'+da.name+'</a>加入</p>');

????????????????c=da.code;

????????????}else?if(da.type=='madd'){

????????????????mkey=da.code;

????????????????da.users.unshift({'code':'all','name':'大家'});

????????????????for(var?i=0;i<da.users.length;i++){

????????????????????var?obj=A.$$('<p>'+da.users[i].name+'</p>');

????????????????????lus.appendChild(obj);

????????????????????if(mkey!=da.users[i].code){

????????????????????????cuser(obj,da.users[i].code);

????????????????????}else{

????????????????????????obj.className='my';

????????????????????????document.title=da.users[i].name;

????????????????????}

????????????????}

????????????????obj=A.$$('<p><span>['+da.time+']</span>歡迎'+da.name+'加入</p>');

????????????????users.all.className='ck';

????????????}

?????????????

????????????if(obj==false){

????????????????if(da.type=='rmove'){

????????????????????var?obj=A.$$('<p class="c2"><span>['+da.time+']</span>'+users[da.nrong].innerHTML+'退出聊天室</p>');

????????????????????lct.appendChild(obj);

????????????????????users[da.nrong].del();

????????????????????delete?users[da.nrong];

????????????????}else{

????????????????????da.nrong=da.nrong.replace(/{\\(\d+)}/g,function(a,b){

????????????????????????return?'<img src="sk/'+b+'.gif">';

????????????????????}).replace(/^data\:image\/png;base64\,.{50,}$/i,function(a){

????????????????????????return?'<img src="'+a+'">';

????????????????????});

????????????????????//da.code 發信息人的code

????????????????????if(da.code1==mkey){

????????????????????????obj=A.$$('<p class="c3"><span>['+da.time+']</span><a>'+users[da.code].innerHTML+'</a>對我說:'+da.nrong+'</p>');

????????????????????????c=da.code;

????????????????????}else?if(da.code==mkey){

????????????????????????if(da.code1!='all')

????????????????????????obj=A.$$('<p class="c3"><span>['+da.time+']</span>我對<a>'+users[da.code1].innerHTML+'</a>說:'+da.nrong+'</p>');

????????????????????????else

????????????????????????obj=A.$$('<p><span>['+da.time+']</span>我對<a>'+users[da.code1].innerHTML+'</a>說:'+da.nrong+'</p>');

????????????????????????c=da.code1;

????????????????????}else?if(da.code==false){

????????????????????????obj=A.$$('<p><span>['+da.time+']</span>'+da.nrong+'</p>');

????????????????????}else?if(da.code1){

????????????????????????obj=A.$$('<p><span>['+da.time+']</span><a>'+users[da.code].innerHTML+'</a>對'+users[da.code1].innerHTML+'說:'+da.nrong+'</p>');

????????????????????????c=da.code;

????????????????????}

????????????????}

????????????}

????????????if(c){

????????????????????obj.children[1].onclick=function(){

????????????????????????users[c].onclick();

????????????????????}

????????????????}

????????????lct.appendChild(obj);

????????????lct.scrollTop=Math.max(0,lct.scrollHeight-lct.offsetHeight);

?????????????

????????}

????}

????A.$('sd').onclick=function(){

????????if(!so){

?????????????return?st();

????????}

????????var?da=A.$('nrong').value.trim();

????????if(da==''){

????????????alert('內容不能為空');

????????????return?false;??

????????}

????????A.$('nrong').value='';

????????so.send('nr='+esc(da)+'&key='+key);

????}

????A.$('nrong').onkeydown=function(e){

????????var?e=e||event;

????????if(e.keyCode==13){

????????????A.$('sd').onclick();

????????}

????}

????function?esc(da){

????????da=da.replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');

????????return?encodeURIComponent(da);

????}

????function?cuser(t,code){

????????users[code]=t;

????????t.onclick=function(){

????????????t.parentNode.children.rcss('ck','');

????????????t.rcss('','ck');

????????????key=code;

????????}

????}

????A.$('ltian').style.height=(document.documentElement.clientHeight - 70)+'px';

????st();

?????

?

????var?bq=A.$('imgbq'),ems=A.$('ems');

????var?l=80,r=4,c=5,s=0,p=Math.ceil(l/(r*c));

????var?pt='sk/';

????bq.onclick=function(e){

????????var?e=e||event;

????????if(!so){

?????????????return?st();

????????}

????????ems.style.display='block';

????????document.onclick=function(){

????????????gb();??

????????}

????????ct();

????????try{e.stopPropagation();}catch(o){}

????}

?????

????for(var?i=0;i<p;i++){

????????var?a=A.$$('<a href="javascript:;">'+(i+1)+'</a>');

????????ems.children[1].appendChild(a);

????????ef(a,i);

????}

????ems.children[1].children[0].className='ck';

?????

????function?ct(){

????????var?wz=bq.weiz();

????????with(ems.style){

????????????top=wz.y-242+'px';

????????????left=wz.x+bq.offsetWidth-235+'px';

????????}

????}

?????????

????function?ef(t,i){

????????t.onclick=function(e){

????????????var?e=e||event;

????????????s=i*r*c;

????????????ems.children[0].innerHTML='';

????????????hh();

????????????this.parentNode.children.rcss('ck','');

????????????this.rcss('','ck');

????????????try{e.stopPropagation();}catch(o){}

????????}

????}

?????

????function?hh(){

????????var?z=Math.min(l,s+r*c);

????????for(var?i=s;i<z;i++){

????????????var?a=A.$$('<img src="'+pt+i+'.gif">');

????????????hh1(a,i);

????????????ems.children[0].appendChild(a);

????????}

????????ct();

????}

?????

????function?hh1(t,i){

????????t.onclick=function(e){

????????????var?e=e||event;

????????????A.$('nrong').value+='{\\'+i+'}';

????????????if(!e.ctrlKey){

????????????????gb();

????????????}

????????????try{e.stopPropagation();}catch(o){}

????????}

????}

?????

????function?gb(){

????????ems.style.display='';

????????A.$('nrong').focus();

????????document.onclick='';

????}

????hh();

????A.on(window,'resize',function(){

????????A.$('ltian').style.height=(document.documentElement.clientHeight - 70)+'px';

????????ct();

????})?

?

????var?fimg=A.$('upimg');

????var?img=new?Image();

????var?dw=400,dh=300;

????A.on(fimg,'change',function(ev){

????????if(!so){

????????????st();

????????????return?false;

????????}

????????if(key=='all'){

????????????alert('由于資源限制 發圖只能私聊');

????????????return?false;??

????????}

????????var?f=ev.target.files[0];

????????if(f.type.match('image.*')){

????????????var?r =?new?FileReader();

????????????r.onload =?function(e){

????????????????img.setAttribute('src',e.target.result);

????????????};

????????????r.readAsDataURL(f);

????????}

????});

????img.onload=function(){

????????ih=img.height,iw=img.width;

????????if(iw/ih > dw/dh && iw > dw){

????????????ih=ih/iw*dw;

????????????iw=dw;

????????}else?if(ih > dh){

????????????iw=iw/ih*dh;

????????????ih=dh;

????????}

????????var?rc = A.$$('canvas');

????????var?ct = rc.getContext('2d');

????????rc.width=iw;

????????rc.height=ih;

????????ct.drawImage(img,0,0,iw,ih);

????????var?da=rc.toDataURL();

????????so.send('nr='+esc(da)+'&key='+key);

????}

?????

})();

</script>

</body>

</html>

參考連接:http://www.jb51.net/article/48019.htm,http://blog.sina.com.cn/s/blog_bf397e780102w25k.html

總結

以上是生活随笔為你收集整理的浅谈php中使用websocket的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。