You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从PHP服务器向Visual Basic客户端推送通知?是否需定时同步数据库?

PHP向Visual Basic Windows客户端发送通知的解决方案

嘿,针对你的两个问题,我来给你梳理清楚可行的方案,不用非得依赖定时同步数据库这种低效的方式!

问题2先明确:不需要定时同步,有主动推送的方法

你完全可以从PHP服务器主动向VB客户端发送通知,和给Android发FCM通知的逻辑类似,只是换了对应的推送机制,不用每隔x分钟去同步数据库查变更。

问题1的具体实现方案

下面是几种靠谱的实现方式,你可以根据自己的场景选择:

方案1:使用WebSocket实现实时双向通信

WebSocket是实现服务器主动推送给客户端的理想方式,支持全双工通信,延迟很低。

PHP服务器端(用Ratchet库实现)

首先安装Ratchet库:

composer require cboden/ratchet

然后写一个简单的WebSocket服务端脚本(比如notification_server.php):

<?php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;

require __DIR__ . '/vendor/autoload.php';

class NotificationServer implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        // 可以在这里记录客户端的标识(比如用户ID),存到数据库或者内存里
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        // 客户端发送的消息,比如注册用户ID
        // 你可以把$from和用户ID关联起来存储
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
    }

    // 自定义方法:给指定用户发送通知
    public function sendToUser($userId, $message) {
        foreach ($this->clients as $client) {
            // 这里需要根据之前存储的用户ID和客户端连接的关联关系判断
            // 比如如果当前client对应的是目标userId,就发送消息
            $client->send(json_encode($message));
        }
    }
}

// 启动WebSocket服务,监听8080端口
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new NotificationServer()
        )
    ),
    8080
);

$server->run();

然后在你现有的PHP业务代码里,当需要发通知给VB客户端时,可以通过HTTP接口触发WebSocket服务的发送逻辑(比如写一个简单的API来调用sendToUser)。

Visual Basic客户端

VB可以使用System.Net.WebSockets.ClientWebSocket来连接WebSocket服务器,接收通知:

Imports System.Net.WebSockets
Imports System.Text

Public Class NotificationClient
    Private Async Sub ConnectToWebSocket()
        Dim client As New ClientWebSocket()
        Await client.ConnectAsync(New Uri("ws://your-php-server-ip:8080"), CancellationToken.None)

        Dim buffer As Byte() = New Byte(1023) {}
        While client.State = WebSocketState.Open
            Dim result As WebSocketReceiveResult = Await client.ReceiveAsync(New ArraySegment(Of Byte)(buffer), CancellationToken.None)
            Dim message As String = Encoding.UTF8.GetString(buffer, 0, result.Count)
            
            // 接收到通知后,显示Windows通知
            ShowNotification(message)
        End While
    End Sub

    Private Sub ShowNotification(message As String)
        // 这里实现Windows原生通知的显示逻辑
        Dim notifyIcon As New NotifyIcon()
        notifyIcon.Icon = SystemIcons.Information
        notifyIcon.BalloonTipTitle = "服务器通知"
        notifyIcon.BalloonTipText = message
        notifyIcon.Visible = True
        notifyIcon.ShowBalloonTip(3000)
    End Sub
End Class

方案2:使用Windows Notification Service (WNS)

就像Android用FCM一样,Windows客户端可以用WNS来接收推送通知,PHP服务器直接调用WNS的API发送通知。

步骤1:VB客户端注册WNS令牌

VB客户端需要向WNS注册,获取推送令牌,然后把这个令牌存储到你的MySQL数据库里(和Android的company_token逻辑一致)。

步骤2:PHP服务器调用WNS API发送通知

在你的现有PHP代码里,添加发送WNS通知的函数:

function sendVbNotification($wnsToken) {
    // 根据通知类型选择WNS端点,这里以Toast通知为例
    $url = "https://db5.notify.windows.com/w/?token=" . urlencode($wnsToken);
    
    $headers = [
        "Content-Type: application/xml",
        "Authorization: Bearer YOUR_WNS_ACCESS_TOKEN",
        "X-WNS-Type: wns/toast"
    ];
    
    $notificationXml = '<?xml version="1.0" encoding="utf-8"?>
<toast>
    <visual>
        <binding template="ToastText01">
            <text id="1">你的服务器通知内容</text>
        </binding>
    </visual>
</toast>';
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $notificationXml);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    return $response;
}

然后在你的业务代码里,获取VB客户端的WNS令牌(类似getCompanyToken,写个getVbClientToken函数),调用这个方法:

// 原有的Android通知代码
sendNotification($company_token);
// 添加VB通知代码
$vbToken = getVbClientToken($user["id"]);
sendVbNotification($vbToken);

注意:WNS需要你在微软开发者平台注册应用,获取对应的密钥和包名,才能生成有效的访问令牌。

方案3:长轮询(备选方案)

如果暂时不想用WebSocket或WNS,可以用长轮询:VB客户端向PHP服务器发起请求,服务器保持连接直到有新通知或者超时,超时后客户端再重新发起请求。这种方式比定时轮询高效,但不如WebSocket实时。

PHP服务器端示例

<?php
require("connection.php");

$userId = $_GET['user_id'];
$lastCheckTime = $_GET['last_check'];

// 检查是否有新通知
$query = "SELECT * FROM notifications WHERE user_id = ? AND created_at > ?";
$stmt = mysqli_prepare($conn, $query);
mysqli_stmt_bind_param($stmt, "is", $userId, $lastCheckTime);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);

if (mysqli_num_rows($result) > 0) {
    $notification = mysqli_fetch_assoc($result);
    echo json_encode($notification);
} else {
    // 等待30秒,期间如果有新通知就返回
    sleep(30);
    // 再次检查
    $query = "SELECT * FROM notifications WHERE user_id = ? AND created_at > ?";
    $stmt = mysqli_prepare($conn, $query);
    mysqli_stmt_bind_param($stmt, "is", $userId, $lastCheckTime);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    echo json_encode(mysqli_fetch_assoc($result) ?: ["status" => "no_notification"]);
}

mysqli_close($conn);

VB客户端示例

Imports System.Net
Imports System.IO
Imports Newtonsoft.Json

Public Class LongPollClient
    Private Async Sub StartLongPoll()
        Dim userId As String = "your-user-id"
        Dim lastCheckTime As String = DateTime.Now.ToString("Y-m-d H:i:s")
        
        While True
            Dim url As String = $"http://your-php-server/long_poll.php?user_id={userId}&last_check={lastCheckTime}"
            Dim request As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
            request.Method = "GET"
            
            Using response As HttpWebResponse = CType(Await request.GetResponseAsync(), HttpWebResponse)
                Using reader As New StreamReader(response.GetResponseStream())
                    Dim responseText As String = Await reader.ReadToEndAsync()
                    Dim notification = JsonConvert.DeserializeObject(Of Notification)(responseText)
                    
                    If notification IsNot Nothing AndAlso notification.status <> "no_notification" Then
                        ShowNotification(notification.message)
                        lastCheckTime = DateTime.Now.ToString("Y-m-d H:i:s")
                    End If
                End Using
            End Using
        End While
    End Sub

    Private Sub ShowNotification(message As String)
        // 同之前的通知显示逻辑
        Dim notifyIcon As New NotifyIcon()
        notifyIcon.Icon = SystemIcons.Information
        notifyIcon.BalloonTipTitle = "服务器通知"
        notifyIcon.BalloonTipText = message
        notifyIcon.Visible = True
        notifyIcon.ShowBalloonTip(3000)
    End Sub
End Class

Public Class Notification
    Public Property status As String
    Public Property message As String
End Class

总结

优先选择WebSocket或者WNS,这两种都是服务器主动推送的方式,比定时同步高效得多。如果你已经熟悉FCM的逻辑,WNS的使用方式和它很类似,都是客户端注册令牌,服务器存储令牌后调用API发送通知。

内容的提问来源于stack exchange,提问作者TonyR81

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 19:02:54