请求反馈:套接字网络摄像头代码 [英] Req feedback: Socket webcam code

查看:119
本文介绍了请求反馈:套接字网络摄像头代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编码员,

这是我的第一个套接字代码,我希望得到一些反馈/改进!

我本人认为,由于长度不正确(我看到高于100%的百分比),分配帧浪费了,我认为读取了错误的8个字节.
但是我不知道如何在不增加某种大延迟的情况下标记开始/结束,这与丢失几帧相同.

谢谢您的宝贵时间!


图片发送代码

Hi Coders,

This is my first socket code and i hoping for some feedback/improvements!

I myself think allot of frames go to waste because of incorrect length (i see percentages above 100%), i think the wrong 8 bytes are read.
But i don''t know how else to mark the start/end without adding some kind of large delay which would be the same as losing several frames.

Thank you for your time!


Image send code

private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
    //Disable new frame event while sending a frame
    if (videoSource != null)
        videoSource.NewFrame -= new NewFrameEventHandler(video_NewFrame);

    Image img = (Image)eventArgs.Frame.Clone();

    NetworkStream nfs = new NetworkStream(camSocket);
    MemoryStream ms = new MemoryStream();

    //Check if already sending a frame
    if (busy == false)
    {
    	//Same image to memory stream
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        //Set boolean to busy
        busy = true;
        int len = 0;
        long rdby = 0;
        byte[] tmp = new byte[8];

        //Send length (8 bytes)
        //Get the length of the memory stream and convert it to 8 bytes and write it to the tmp array
        BitConverter.GetBytes(ms.Length).CopyTo(tmp, 0);
        nfs.Write(tmp, 0, tmp.Length);

        //Send File
        ms.Seek(0, SeekOrigin.Begin);
        tmp = new byte[1024];
        while (rdby < ms.Length && nfs.CanWrite)
        {
            len = ms.Read(tmp, 0, tmp.Length);
            nfs.Write(tmp, 0, len);
            rdby = rdby + len;
        }
        ms.Close();
        busy = false;
        
    }

    //reattach event for new frames
    if (videoSource != null)
        videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
}



图片接收代码



Image receive code

public void WaitForData(SocketPacket s)
{
        if (pfnWorkerCallBack == null) 
        {
            pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
        }
//Read 8 bytes (image length)
        s.currentSocket.BeginReceive(s.Buffer, 0, 8, SocketFlags.None, 	pfnWorkerCallBack, s);
}

public void OnDataReceived(IAsyncResult asyn)
{
    SocketPacket s = (SocketPacket)asyn.AsyncState;

    NetworkStream nfs = new NetworkStream(s.currentSocket);

    byte[] tmp = new byte[1024];
    
    //Convert the 8 read bytes (from BeginReceive) to file length
    long length = BitConverter.ToInt64(s.Buffer, 0);
    long read = 0;

    MemoryStream ms = new MemoryStream();
    while (read < length)
    {
        byte[] buffer = new byte[1024];
        int i = nfs.Read(buffer, 0, buffer.Length);
        ms.Write(buffer, 0, i);
        read = read + i;

        //Calculate percentage done
        int pc = (int)(((double)read / (double)length) * 100.00);
		log(pc + "%");
    }

    ms.Seek(0, SeekOrigin.Begin);
    
    //Invoke new frame event
    if (nImage != null)
        nImage(Image.FromStream(ms));

    WaitForData(s);
}



套接字设置



Socket setup

public Webcam()
{
    mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 1402);
    mainSocket.Bind(ipLocal);
    mainSocket.Listen(-1);

    mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
}

public void OnClientConnect(IAsyncResult asyn)
{
        Socket workerSocket = mainSocket.EndAccept(asyn);

        SocketPacket SocPkt = new SocketPacket(workerSocket);

        WaitForData(SocPkt);
        mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
}

推荐答案

以下是我的反馈意见:

像8、1024、1402、100这样的硬编码立即数非常糟糕.您将如何维护此类代码?解决方案非常简单:将它们声明为显式常量.这样,您可以轻松地重用它们,进行一致的修改并将所有或其中一些移至数据文件,资源或所需的任何内容.

video_NewFrame这样的名称违反了(好的)Microsoft命名约定.

最后,使用异步API的整个想法对我来说非常可疑.我认为,当多线程并不常见时,这些API就会兴旺发展,但是即使那样,我还是非常喜欢线程.如今,使用同步API进行多线程已变得更加实用.您使用了同步API,这意味着一些阻塞调用,但这不是问题,因为您是在一些单独的线程中执行它的.它使逻辑更加线性和可观察.即使当您需要复杂的线程同步时,也可以通过为线程同步设计的常规方法来解决此问题,而不是使用特定于所使用的特定异步API的方法.同样,这也使您减少工作量,获得了更具可读性,可维护性和可靠性的结果.

—SA
Here is my feedback:

Hard-coded immediate constants like 8, 1024, 1402, 100 are quite bad. How would you maintain such code? And the solution is so simple: declare them as explicit constants. This way, you can easily reuse them, modify consistently and move all or some of them to data files, resources or whatever is needed.

The names like video_NewFrame violate (good) Microsoft naming conventions.

Finally, the whole idea of using asynchronous API looks very questionable to me. I think that those APIs flourished when multithreading was not a common place, but even then I highly preferred threading. These days, multithreading with synchronous API is much more practical. You use synchronous API, which means some blocking calls, but this is not a problem because you execute it in some separate thread. It makes the logic more linear and observable. Even when you need complex thread synchronization, you solve this problem in a general ways designed for thread synchronization, not in ways specific to the particular asynchronous API you use. This, too, lets you do to less work with more readable, maintainable and reliable results.

—SA


这篇关于请求反馈:套接字网络摄像头代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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