在之前的项目中,就曾据说过swoole的大名,想用来进行消息推送,可是当时只是有了初步的了解,并不敢大胆的运用到线上产品。所谓 识不足则多虑,威不足则多怒、因此就是怕,只能跟领导说了运用极光的推送功能,并且还说出了必定的理由,领导天然也只有相信了,那就用极光推送吧!php
最近闲来无事,又从新温习了一下swoole的消息通知功能,虽然在项目开发当时,也曾实现过简单的操做的,可是此次温习更加深了学习,配合vb.net进行开发,感受仍是棒棒哒,下面是一套实现过程,若有须要参考,请拿去,不谢!html
首先,个人开发平台是windows,虽然本人也装有virtual box虚拟机,可是那玩意儿太耗内存cpu了,开起来搞实在不想搞。因此,就用了cygwin进行配置开发环境搭建,这里我就不说具体安装步骤了,给个连接吧,一步步按着操做就好了。 查看php在window下安装swoole扩展的方法 请点击。 ps: 若是你win系统里已经安装了一套wamp环境,在cygwin中使用php或其余和win有相同名称命令时,请记得使用全路径 如:/bin/php index.php , /bin/find / -name "init*"redis
第二步、编写php服务端程序,命名 test_tcp_server.php , 代码以下:数据库
<?php $serv = new swoole_server("127.0.0.1", 9501); $serv->set(array( 'worker_num' => 2, //工做进程数量 // 'daemonize' => true, //是否做为守护进程,玩玩就不要开启这东西了,否则你都不知道跑到哪里去了 )); $serv->on('connect', 'my_onConnect'); $serv->on('receive', 'my_onReceive'); $serv->on('close', 'my_onClose'); echo "swoole_server is running on 127.0.0.1 9501 \n"; $serv->start(); //receive msg respond function my_onReceive ($serv, $fd, $from_id, $data) { // var_dump($serv); $data = trim($data); // 发送给谁, 如:@id msg... , 最好的固然是使用redis或者数据库存入号码并生成一个映射了,不过玩玩就不要认真了 if(substr($data, 0, 1) == '@'){ $splitStart = strpos($data, ' '); $toUserId = substr($data, 1, $splitStart - 1); echo 'Send to:' . $toUserId . ';'; $content = substr($data, $splitStart + 1); if(is_numeric($toUserId)){ $serv->send($toUserId, "From Client[$fd@$from_id]:" . $content); }elseif(strtolower($toUserId) == 'all'){ broadcast($serv, $fd, $content); }else{ $serv->send($fd, 'Swoole: Unkown to user ' . strtolower($toUserId) . ' infomation.'); } }else{ echo "From Client[$fd@$from_id],received data: " . $data . PHP_EOL; $serv->send($fd, 'Swoole: '.$data); } // $serv->close($fd); } //connect action function my_onConnect ($serv, $fd){ echo "Client:Connect. id:{$fd}\n"; } //close action function my_onClose ($serv, $fd) { echo "Client: Close. id:{$fd}\n"; } //broadcast except me, 只会广播from_id相同的用户,再研究了 function broadcast(swoole_server $serv, $fd = 0, $data = "hello") { $start_fd = 0; $sendNum = 0; echo "broadcast to "; $from = "From Client[$fd]:"; while(true) { $conn_list = $serv->connection_list($start_fd, 10); if($conn_list === false) { break; } var_dump($conn_list); $start_fd = end($conn_list); foreach($conn_list as $conn) { if($conn === $fd) continue; $ret1 = $serv->send($conn, $from . $data); $sendNum ++; } } echo $sendNum . ' numbers.'; }
记得把它跑起来哦windows
/bin/php test_tcp_server.php
第三步,你能够编写一个客户端程序,也能够不用编写,由于其余工具也彻底能够链接进行的呢!若是要定,能够参考swoole官网的tcp_client代码,以下:服务器
<?php $client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC); //设置事件回调函数 $client->on("connect", function($cli) { $cli->send("hello world\n"); }); $client->on("receive", function($cli, $data){ echo "Received: ".$data."\n"; }); $client->on("error", function($cli){ echo "Connect failed\n"; }); $client->on("close", function($cli){ echo "Connection close\n"; }); //发起网络链接 $client->connect('127.0.0.1', 9501, 0.5);
正常的话,运行这个脚本,你就能够收到消息了如: 'From Client[1@0],received data: hello,world'swoole
第四步、你确定不知足于使用php语言去链接服务器端,你固然不该该知足!你还可使用windows的cmd命令行嘛,以下:网络
telnet 127.0.0.1 9501
而后,你会发现,怎么只输入了一个字符就发送了。缘由是什么win的telnet协议之类的,使用send命令,就能够了。操做为:按键 ctrl + ] ,进入telnet 命令行模式,输入send aaaddd异步
ok,多开几个客户端,看起来会话就能够了呢(要查看返回的内容,直接按Enter键便可,切换回来使用ctrl + ]),来看看服务端都什么样子吧:socket
都是有响应的吧,ok了,如今再试试一个功能, send @10 hello,10, you ok ? ,则另外一个客户端就收到消息了
ok,到此为止,基本上测试完成了。可是使用cmd毕竟看起来不爽,因而想到用vb.net去实现一个客户端。代码就简要的贴出来,看看吧。
第五步,使用vb.net实现客户端访问:
Imports System Imports System.Net Imports System.Net.Sockets Imports System.Text Public Class SynchronousSocketClient Protected Shared port As Integer = 9501 Protected Shared host As String = "localhost" Private Shared sender As Socket Public Shared bytes(1024) As Byte ' A way to the connect to the server Public Shared Sub Main() If (IsNothing(sender)) OrElse Not sender.Connected Then If Not IsNothing(Form1.TextBox1.Text) Then host = Form1.TextBox1.Text End If If (Form1.TextBox2.Text) Then port = Form1.TextBox2.Text End If sender = ConnectSocket(host, port) End If End Sub ' send something to server Public Shared Sub send() If (IsNothing(sender)) OrElse Not sender.Connected Then If Not IsNothing(Form1.TextBox1.Text) Then host = Form1.TextBox1.Text End If If (Form1.TextBox2.Text) Then port = Form1.TextBox2.Text End If sender = ConnectSocket(host, port) End If ' Encode the data string into a byte array. Dim msg As Byte() = Encoding.ASCII.GetBytes(Form1.myContent.Text) ' Send the data through the socket. Dim bytesSent As Integer = sender.Send(msg) ' Receive the response from the remote device. Dim bytesRec As Integer = sender.Receive(bytes) Console.WriteLine("ServerReturn = {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec)) Form1.infoText.Text &= "ServerReturn = " & Encoding.ASCII.GetString(bytes, 0, bytesRec) & vbNewLine End Sub ' connect initialize Private Shared Function ConnectSocket(ByVal host As String, ByVal port As Integer) As Socket '建立链接 Dim s As Socket = Nothing Dim hostEntry As IPHostEntry = Nothing 'address = System.Net.IPAddress.Parse(host) Dim ipHostInfo As IPHostEntry = Dns.Resolve(host) Dim address As IPAddress = ipHostInfo.AddressList(0) Dim endPoint As New IPEndPoint(address, port) Dim tempSocket As New Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) tempSocket.Connect(endPoint) If tempSocket.Connected Then s = tempSocket Console.WriteLine("Socket connected to {0}", tempSocket.RemoteEndPoint.ToString()) Form1.infoText.Text &= "Socket connected to " & tempSocket.RemoteEndPoint.ToString() End If Return s End Function ' close socket Public Shared Sub closeSocket() If (sender.Connected) Then Form1.infoText.Text &= "Socket closed : " & sender.RemoteEndPoint.ToString() & vbNewLine sender.Shutdown(SocketShutdown.Both) sender.Close() End If End Sub End Class 'SynchronousSocketClient
如上是访问链接服务器的代码,触发代码则是在另外一个页面进行的,界面以下:
运行后效果以下:
触发事件的代码就比较简单了,仍是贴一下吧:
Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'Console.WriteLine("console ", Rnd) ' 没法读取最后一行console其实 SynchronousSocketClient.Main() 'AsynchronousClient.Main() ' 异步功能并未实现呢 End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click infoText.Text = "" End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click SynchronousSocketClient.send() End Sub Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click SynchronousSocketClient.closeSocket() End Sub End Class
到此,打完,收工。因为异步的调试没有成功,就此打住吧,之后有兴趣再去搞了!