从 C# 应用程序到 PHP 网页的 UDP 流传输 [英] UDP Streaming transfer from C# application to PHP webpage

查看:24
本文介绍了从 C# 应用程序到 PHP 网页的 UDP 流传输的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写 C# UDP 服务器.它从客户端接收一个特定的 ID,并返回与之关联的歌曲.客户端是一个 PHP 网页,并将接收到的字节存储到一个文件中.现在我正在做一些测试,试图在传输为 2048 字节时简单地开始这首歌的假讲座(只是一个 javascript 警报).但是我有很多错误...... PHP 页面似乎在收到所有数据之前完成了到文件的传输......服务器继续发送字节但文件是完整的,重量很好,所有......

I'm trying to code a C# UDP server. It receives a specific ID from the client, and return the song associated with it. The client is a PHP webpage, and stocks the bytes received into a file. Right now I'm doing some tests, trying to simply start a fake lecture of the song (just a javascript alert) when the transfer is at 2048 bytes. But I have plenty of bugs... The PHP page seems to finish the transfer into the file BEFORE having received all the data... The server continue to send bytes but the file is complete, with the good weight and all...

我知道我的英语不是很好,所以如果你不明白什么,就问吧!

I know I don't have a very good english, so if you don't undersood something, just ask !

这是 C# 代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;  
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Data.SQLite;

namespace cdCollector
{
public partial class Streaming : Form
{
    private static List<IPAddress> clients_ = new List<IPAddress>();

    public Streaming()
    {
        InitializeComponent();
        listen();
    }

    public class ThreadClient
    {
        private static UdpClient socket_;
        private static IPEndPoint ipepClient_;
        private static int noChanson_;
        private static SQLiteConnection connexion_;

        public void setSocket(ref UdpClient socket) { socket_ = socket; }
        public void setIpepClient(ref IPEndPoint ipepClient) { ipepClient_ = ipepClient; }
        public void setNoChanson(int noChanson) { noChanson_ = noChanson; }
        public void setConnexion(ref SQLiteConnection connexion) { connexion_ = connexion; }

        public static void send()
        {
            try
            {
                while (Thread.CurrentThread.IsAlive)
                {
                    Chanson uneChanson;
                    FileStream stream;
                    byte[] buffer = new byte[1024];
                    int read;

                    uneChanson = new Chanson(noChanson_);
                    uneChanson.load(ref connexion_);

                    stream = new FileStream("C:\\Users\\Julie\\Documents\\toune.flac", FileMode.Open, FileAccess.Read);

                    socket_.Send(Encoding.ASCII.GetBytes(stream.Length.ToString()), stream.Length.ToString().Length, ipepClient_);

                    while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                        socket_.Send(buffer, buffer.Length, ipepClient_);

                    Console.WriteLine("finished");
                }
            }
            catch (ThreadAbortException tae)
            { }
            catch (Exception)
            {
                Thread.CurrentThread.Abort();
            }
        }
    }

    public static void listen()
    {
        byte[] data = new byte[1024];

        IPEndPoint ipepServer = new IPEndPoint(IPAddress.Any, 7575); // IP du serveur
        IPEndPoint ipepClient = new IPEndPoint(IPAddress.Any, 0); // IP du client;
        UdpClient socket = new UdpClient(ipepServer); // socket serveur
        int noChanson;
        SQLiteConnection connexion = new SQLiteConnection("Data Source=" + Application.StartupPath + "\\cdCollector.db");
        SQLiteCommand command = new SQLiteCommand(connexion);
        SQLiteDataReader dr;
        Thread thread;

        connexion.Open();

        while (true)
        {
            try
            {
                Console.WriteLine("Waiting for a client...");

                data = socket.Receive(ref ipepClient);

                Console.WriteLine("Message received from {0}:", ipepClient.ToString());
                Console.WriteLine(Encoding.ASCII.GetString(data, 0, data.Length));



                command.CommandText = "SELECT KeyLocale FROM AssocKeys WHERE NomTable = 'Chanson' AND KeyWeb = "
                                        + int.Parse(Encoding.ASCII.GetString(data, 0, data.Length));

                dr = command.ExecuteReader();


                if (dr.HasRows)
                {
                    dr.Read();

                    noChanson = dr.GetInt32(0);

                    dr.Close();

                    ThreadClient client = new ThreadClient();
                    client.setConnexion(ref connexion);
                    client.setIpepClient(ref ipepClient);
                    client.setNoChanson(noChanson);
                    client.setSocket(ref socket);

                    thread = new Thread(new ThreadStart(ThreadClient.send));
                    thread.Start();
                }
                else
                    socket.Send(Encoding.ASCII.GetBytes("Erreur: Chanson introuvable"), ("Erreur: Chanson introuvable").Length, ipepClient);



            }
            catch (SocketException se)
            {
                Console.WriteLine("Erreur Socket:" + se.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Erreur: " + ex.Message);
            }

        }

        connexion.Close();
    }

}   

}

和 PHP 代码:

<?php
 session_start();
$address="192.168.2.2";
$read = false;
$port = 7575;
$length = 0;
$started = false;

if (isset($port) and
($socket=socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) and
(socket_connect($socket, $address, $port)))
{
    $text =  "Connection successful on IP $address, port $port <br />";

    $from = '';
    $port = 0;
    $length = 0;

    socket_send( $socket, $_GET['no'], 1024, MSG_EOR );
    socket_recvfrom( $socket, $buf, 1024, 12, $from, $port);

    $lengthTotal = $buf;
    echo "Taille prévue du fichier: " . $lengthTotal . "<br />";

    if( file_exists( "temp" . $_SESSION['ID_Membre'] . ".flac" ) )
        unlink("temp" . $_SESSION['ID_Membre'] . ".flac");

    $file = fopen("temp" . $_SESSION['ID_Membre'] . ".flac", 'a');
    $buf = null;

    while( $length < $lengthTotal )
    {
        $length += socket_recvfrom( $socket, $buf, 1024, 12, $from, $port );
        if( $length > 2048 && !$started )
        {
            ?>
            <script type="text/javascript">
            <!--
                alert("Lecture...");
            //->
            </script>
            <?php
            $started = true;
        }

        fputs($file, $buf);

        flush();
    }

    echo "<br />" . $length . "<br />";
    fclose($file);
}
else
        $text="Unable to connect<pre>".socket_strerror(socket_last_error())."</pre>";

echo $text;
?>

非常感谢!

推荐答案

UDP 是一种本质上不可靠的传输.您需要在 UDP 之上实现确认、超时、重传和序列号,以保证所有数据按预期顺序传输,除非您的客户端应用程序可以承受丢弃的数据包.如果您需要在服务器和客户端之间保证数据传输并且不想自己实现所有这些东西(这可能需要包括客户端缓冲来重新排列),我建议您考虑使用 TCP 套接字-顺序数据报).如果您想要 UDP 之上的可靠性,我建议您阅读有关该主题的优秀教科书(例如 W. Richard Stevens 等撰写的Unix Network Programming").

UDP is an inherently unreliable transport. You will need to implement acknowledgements, timeouts, retransmissions and sequence numbers on top of UDP in order to guarantee transmission of all of your data in the expected order, unless your client application can live with dropped packets. I would advise you to consider using TCP sockets instead if you need guaranteed transmission of data between server and client and don't want to have to implement all of this stuff yourself (which might need to include client-side buffering to rearrange out-of-order datagrams). If you want reliability on top of UDP, I would advise you to read a good textbook on the subject (e.g. "Unix Network Programming" by W. Richard Stevens etc.).

TCP 上的指针:

您应该查看 System.Net.Sockets.TcpClientSystem.Net.Sockets.TcpListener 以了解 C# 方面的内容并查阅 PHP 文档,了解有关 PHP 方面的信息.

You should take a look at System.Net.Sockets.TcpClient and System.Net.Sockets.TcpListener for the C# side of things and consult the PHP documentation for info on the PHP side of things.

使用 TCP 套接字并没有太大的不同,除了您将使用 sendrecv(或 C#/PHP 等价物)而不是 send_torecv_from.设置服务器端的事情有点复杂,因为您需要bindlisten 等,但有很多资源,例如:

Using TCP sockets isn't really that much different except you'll be using send and recv (or C#/PHP equivalents) instead of send_to and recv_from. Setting up the server side of things is a little more complicated since you need to bind and listen etc. but there are plenty of resources, e.g.:

http://www.switchonthecode.com/tutorials/csharp-tutorial-simple-threaded-tcp-server

这篇关于从 C# 应用程序到 PHP 网页的 UDP 流传输的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆