皮皮网

【小程序+直播源码】【原生music源码详解】【图库源码自动采集】atsend源码

2024-11-20 03:27:58 来源:代运源码市场

1.Dubbo调用超时那些事儿
2.vb问题:希望可以给代码
3.ESP8266 STM32 HTTP json透传实验
4.gRPC 流量控制详解
5.在线等啊,源码有人出过这个问题没有 java.lang.IllegalStateException: Broadcast already finished

atsend源码

Dubbo调用超时那些事儿

       其实之前很早就看过Dubbo源码中关于超时这部分的源码处理逻辑,但是源码没有记录下来,最近在某脉上看到有人问了这个问题,源码想着再回顾一下。源码

开始

       从dubbo的源码小程序+直播源码请求开始,看看dubbo(2.6.6)在超时这块是源码怎么处理的:

com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeChannel#request(java.lang.Object, int)@Overridepublic ResponseFuture request(Object request, int timeout) throws RemotingException { if (closed) { throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!");}// create request.Request req = new Request();req.setVersion(Version.getProtocolVersion());req.setTwoWay(true);req.setData(request);DefaultFuture future = new DefaultFuture(channel, req, timeout);try { channel.send(req);} catch (RemotingException e) { future.cancel();throw e;}return future;}DefaultFuture

       从返回值ResponseFuture类型可以看出,这是源码一个异步方法(不等同于Dubbo的异步调用)。那么调用超时的源码关键可以从ResponseFuture来看:

public interface ResponseFuture { Object get() throws RemotingException;Object get(int timeoutInMillis) throws RemotingException;void setCallback(ResponseCallback callback);boolean isDone();}

       可以看到这是一个接口,从request方法可以得知实现类是源码DefaultFuture,从构造函数入手:

public DefaultFuture(Channel channel,源码 Request request, int timeout) { this.channel = channel;this.request = request;this.id = request.getId();this.timeout = timeout > 0 ? timeout : channel.getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);// put into waiting map.FUTURES.put(id, this);CHANNELS.put(id, channel);}

       可以得知每一个DefaultFuture都有一个id,并且等于requestId,源码timeout是源码从url中获取的配置,没有时默认ms。源码

       从代码的源码注释可以看到FUTURES这个map应该就是关键,是一个waiting map。

       DefaultFuture中还有一个方法:

public static void received(Channel channel, Response response) { try { DefaultFuture future = FUTURES.remove(response.getId());if (future != null) { future.doReceived(response);} else { logger.warn("The timeout response finally returned at "+ (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()))+ ", response " + response+ (channel == null ? "" : ", channel: " + channel.getLocalAddress()+ " -> " + channel.getRemoteAddress()));}} finally { CHANNELS.remove(response.getId());}}

       可以看到调用的地方为:

       com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler#received

@Overridepublic void received(Channel channel, Object message) throws RemotingException { //省略一些代码} else if (message instanceof Response) { handleResponse(channel, (Response) message);//省略一些代码}}

       com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler#handleResponse

static void handleResponse(Channel channel, Response response) throws RemotingException { if (response != null && !response.isHeartbeat()) { DefaultFuture.received(channel, response);}}

       回到DefaultFuture.received,可以看到通过Response id从FUTURES中拿了一个DefaultFuture出来,然后调用了doReceived方法,也就是说Response id和Request id 相同。结下来看看doReceived做了什么:

private void doReceived(Response res) { lock.lock();try { response = res;if (done != null) { done.signal();}} finally { lock.unlock();}if (callback != null) { invokeCallback(callback);}}

       首先是原生music源码详解加锁,然后通过唤醒了阻塞在Condition上的线程。看看什么地方会阻塞在done这个条件上:

@Overridepublic Object get(int timeout) throws RemotingException { if (timeout <= 0) { timeout = Constants.DEFAULT_TIMEOUT;}if (!isDone()) { long start = System.currentTimeMillis();lock.lock();try { while (!isDone()) { done.await(timeout, TimeUnit.MILLISECONDS);if (isDone() || System.currentTimeMillis() - start > timeout) { break;}}} catch (InterruptedException e) { throw new RuntimeException(e);} finally { lock.unlock();}if (!isDone()) { throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));}}return returnFromResponse();}

       是get方法,get方法确实在request请求后被调用:

(Result) currentClient.request(inv, timeout).get()

       可以看到get方法的大致逻辑为,先获取锁,然后循环判断isDone,并阻塞等到条件,当条件超时,如果任务完成,或者超过timeout结束循环,接着判断isDone,图库源码自动采集如果超时抛出TimeoutException。并且通过sent(request请求时间)是否>0()来判断是clientSide还是serverSide超时。

       isDone逻辑如下:

@Overridepublic boolean isDone() { return response != null;}

       如果是正常Response,也有可能是超时的现象,可以看到get方法最后调用了一个函数:

public interface ResponseFuture { Object get() throws RemotingException;Object get(int timeoutInMillis) throws RemotingException;void setCallback(ResponseCallback callback);boolean isDone();}0TIMEOUT SIDE

       SERVER_TIMEOUT(服务端超时): 这个就是正常的我们消费端请求一个RPC接口,服务端由于性能等一些原因处理时间超过了timeout配置时间。

       CLIENT_TIMEOUT:我们可以看到是通过sent(上面有说sent>0)这个来判断是否clientTimeout,那么这个sent什么时候改变呢?就在发送请求的地方:

public interface ResponseFuture { Object get() throws RemotingException;Object get(int timeoutInMillis) throws RemotingException;void setCallback(ResponseCallback callback);boolean isDone();}1

       也就是说handler.sent一旦调用成功返回,那么就不算clientSide Timeout了。那么CLIENT_TIMEOUT大概率就是花花娱乐源码教程由于client端网络,系统等原因超时。

原文:/post/

vb问题:希望可以给代码

       先新建一个模块,里面添加API声明

       Option Explicit

       Declare Function MoveWindow Lib "user" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long

       Declare Function SendMessage Lib "user" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

       Public Const LB_INITSTORAGE = &H1A8

       Public Const LB_ADDSTRING = &H

       Public Const WM_SETREDRAW = &HB

       Public Const WM_VSCROLL = &H

       Public Const SB_BOTTOM = 7

       Declare Function GetLogicalDrives Lib "kernel" () As Long

       Declare Function FindFirstFile Lib "kernel" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN_FIND_DATA) As Long

       Public Const INVALID_HANDLE_VALUE = -1

       Declare Function FindNextFile Lib "kernel" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN_FIND_DATA) As Long

       Declare Function FindClose Lib "kernel" (ByVal hFindFile As Long) As Long

       Type FILETIME

       dwLowDateTime As Long

       dwHighDateTime As Long

       End Type

       Public Const MaxLFNPath =

       Type WIN_FIND_DATA

       dwFileAttributes As Long

       ftCreationTime As FILETIME

       ftLastAccessTime As FILETIME

       ftLastWriteTime As FILETIME

       nFileSizeHigh As Long

       nFileSizeLow As Long

       dwReserved0 As Long

       dwReserved1 As Long

       cFileName As String * MaxLFNPath

       cShortFileName As String *

       End Type

       然后在窗体上制作2个菜单,放置一个ListBox和一个PictureBox

       完整代码如下:

       Option Explicit

       Dim PicHeight%, hLB&, FileSpec$, UseFileSpec%

       Dim TotalDirs%, TotalFiles%, Running%

       Dim WFD As WIN_FIND_DATA, hItem&, hFile&

       Const vbBackslash = "\"

       Const vbAllFiles = "*.*"

       Const vbKeyDot =

       Private Sub Form_Load()

       ScaleMode = vbPixels

       PicHeight% = Picture1.Height

       hLB& = List1.hwnd

       SendMessage hLB&, LB_INITSTORAGE, &, ByVal & *

       Move (Screen.Width - Width) * 0.5, (Screen.Height - Height) * 0.5

       End Sub

       Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)

       If KeyCode = vbKeyEscape And Running% Then Running% = False

       End Sub

       Private Sub Form_Resize()

       MoveWindow hLB&, 0, 0, ScaleWidth, ScaleHeight - PicHeight%, True

       End Sub

       Private Sub Form_Unload(Cancel As Integer)

       Set Form1 = Nothing

       End

       End Sub

       Private Sub mnuFindFiles_Click()

       If Running% Then: Running% = False: Exit Sub

       Dim drvbitmask&, maxpwr%, pwr%

       On Error Resume Next

       FileSpec$ = InputBox("Enter a file spec:" & vbCrLf & vbCrLf & "Searching will begin at drive A and continue " & "until no more drives are found. " & "Click Stop! at any time." & vbCrLf & "The * and ? wildcards can be used.", "Find File(s)", "*.exe")

       If Len(FileSpec$) = 0 Then Exit Sub

       MousePointer =

       Running% = True

       UseFileSpec% = True

       mnuFindFiles.Caption = "&Stop!"

       mnuFolderInfo.Enabled = False

       List1.Clear

       drvbitmask& = GetLogicalDrives()

       If drvbitmask& Then

       maxpwr% = Int(Log(drvbitmask&) / Log(2))

       For pwr% = 0 To maxpwr%

       If Running% And (2 ^ pwr% And drvbitmask&) Then _

       Call SearchDirs(Chr$(vbKeyA + pwr%) & ":\")

       Next

       End If

       Running% = False

       UseFileSpec% = False

       mnuFindFiles.Caption = "&Find File(s)..."

       mnuFolderInfo.Enabled = True

       MousePointer = 0

       Picture1.Cls

       Picture1.Print "Find File(s): " & List1.ListCount & " items found matching " & """" & FileSpec$ & """"

       Beep

       End Sub

       Private Sub mnuFolderInfo_Click()

       If Running% Then: Running% = False: Exit Sub

       Dim searchpath$

       On Error Resume Next

       searchpath$ = InputBox("输入要查找的目标路径", "文件夹信息", "C:\")

       If Len(searchpath$) < 2 Then Exit Sub

       If Mid$(searchpath$, 2, 1) <> ":" Then Exit Sub

       If Right$(searchpath$, 1) <> vbBackslash Then searchpath$ = searchpath$ & vbBackslash

       If FindClose(FindFirstFile(searchpath$ & vbAllFiles, WFD)) = False Then

       End If

       MousePointer =

       Running% = True

       mnuFolderInfo.Caption = "停止(&S)"

       mnuFindFiles.Enabled = False

       List1.Clear

       TotalDirs% = 0

       TotalFiles% = 0

       Call SearchDirs(searchpath$)

       Running% = False

       mnuFolderInfo.Caption = "文件夹信息(&F)"

       mnuFindFiles.Enabled = True

       Picture1.Cls

       MousePointer = 0

       MsgBox "Total folders: " & vbTab & TotalDirs% & vbCrLf & "Total files: " & vbTab & TotalFiles%, , "Folder Info for: " & searchpath$

       End Sub

       Private Sub SearchDirs(curpath$)

       Dim dirs%, dirbuf$(), i%

       Picture1.Cls

       Picture1.Print "Searching " & curpath$

       DoEvents

       If Not Running% Then Exit Sub

       hItem& = FindFirstFile(curpath$ & vbAllFiles, WFD)

       If hItem& <> INVALID_HANDLE_VALUE Then

       Do

       If (WFD.dwFileAttributes And vbDirectory) Then

       If Asc(WFD.cFileName) <> vbKeyDot Then

       TotalDirs% = TotalDirs% + 1

       If (dirs% Mod ) = 0 Then ReDim Preserve dirbuf$(dirs% + )

       dirs% = dirs% + 1

       dirbuf$(dirs%) = Left$(WFD.cFileName, InStr(WFD.cFileName, vbNullChar) - 1)

       End If

       ElseIf Not UseFileSpec% Then

       TotalFiles% = TotalFiles% + 1

       End If

       Loop While FindNextFile(hItem&, WFD)

       Call FindClose(hItem&)

       End If

       If UseFileSpec% Then

       SendMessage hLB&, WM_SETREDRAW, 0, 0

       Call SearchFileSpec(curpath$)

       SendMessage hLB&, WM_VSCROLL, SB_BOTTOM, 0

       SendMessage hLB&, WM_SETREDRAW, 1, 0

       End If

       For i% = 1 To dirs%: SearchDirs curpath$ & dirbuf$(i%) & vbBackslash: Next i%

       End Sub

       Private Sub SearchFileSpec(curpath$)

       hFile& = FindFirstFile(curpath$ & FileSpec$, WFD)

       If hFile& <> INVALID_HANDLE_VALUE Then

       Do

       DoEvents

       If Not Running% Then Exit Sub

       SendMessage hLB&, LB_ADDSTRING, 0, ByVal curpath$ & Left$(WFD.cFileName, InStr(WFD.cFileName, vbNullChar) - 1)

       Loop While FindNextFile(hFile&, WFD)

       Call FindClose(hFile&)

       End If

       End Sub

       程序运行时就能够通过输入文件名而进行模糊查找了

       如果还不明白,就加我QQ,我把我做好的程序发给你看

       QQ号:

ESP STM HTTP json透传实验

       本文将介绍ESP与STM进行HTTP JSON透传实验的详细步骤。首先,通过建立HTTP虚拟测试桩,利用SoapUI模拟远端HTTP服务器进行测试。

       接着,psd展示网站源码ESP需进入透传配置。具体步骤如下:

       设置WIFI模式:使用AT+CWMODE=3命令,将模块设置为ap+sta共存模式。

       重启模块:执行AT+RST命令,重启ESP。

       重启后,可能会出现乱码现象,这是由于模块上电时波特率偏高,随后自动调整至。

       连接路由器:使用AT+CWJAP命令,输入路由器的SSID和密码。

       查询设备IP:执行AT+CIFSR命令,获取设备的IP地址。

       然后,ESP需连接远端服务器(通过TCP协议)。具体步骤如下:

       使用AT+CIPSTART命令,传入服务器IP和端口号。

       开启ESP透传模式:执行AT+CIPMODE=1命令。

       透传开始时,通过AT+CIPSEND命令确保串口输入的字符能成功传送到服务器端。

       接着,将数据通过HTTP形式发送至远端服务器。数据格式以JSON形式为主,URL构造为服务器IP和端口号,如:...:/test/...。同时,需设置正确的Host、Content-Type和Content-Length字段。

       HTTP服务器接收到JSON数据后,会返回 OK字符串,表示数据上传成功。整个数据包的协议格式包含devicetype、time、idno、type等关键信息。

       封装头部和数据部分后,实现将整个数据上传至服务器的函数。最后,调用API执行程序,确保串口接收到服务器的回复。

       完成实验后,可参考完整源码获取。关注公众号“嵌入式云IOT技术圈”,发送关键词“ESP”即可获取。

gRPC 流量控制详解

       gRPC 流量控制详解

       流量控制, 一般来说指的是在网络传输中, 发送者主动限制自身发送数据的速率或发送的数据量, 以适应接收者处理数据的速度. 当接收者的处理速度较慢时, 来不及处理的数据会被存放在内存中, 而当内存中的数据缓存区被填满之后, 新收到的数据就会被扔掉, 导致发送者不得不重新发送, 就会造成网络带宽的浪费.

       流量控制是一个网络组件的基本功能, 我们熟知的 TCP 协议就规定了流量控制算法. gRPC 建立在 TCP 之上, 也依赖于 HTTP/2 WindowUpdate Frame 实现了自己在应用层的流量控制.

       在 gRPC 中, 流量控制体现在三个维度:

       采样流量控制: gRCP 接收者检测一段时间内收到的数据量, 从而推测出 on-wire 的数据量, 并指导发送者调整流量控制窗口.

       Connection level 流量控制: 发送者在初始化时被分配一个 quota (额度), quota 随数据发送减少, 并在收到接收者的反馈之后增加. 发送者在耗尽 quota 之后不能再发送数据.

       Stream level 流量控制: 和 connection level 的流量控制类似, 只不过 connection level 管理的是一个发送者和一个接收者之间的全部流量, 而 stream level 管理的是 connection 中诸多 stream 中的一个.

       在本篇剩余的部分中, 我们将结合代码一起来看看这三种流量控制的实现原理和实现细节.

       本篇中的源代码均来自 androiddocs/src/trunk/core/java/android/content/BroadcastReceiver.java

        public void sendFinished(IActivityManager am) {

        synchronized (this) {

        if (mFinished) {

        throw new IllegalStateException("Broadcast already finished");

        }

        mFinished = true;

       估计是重复调用finish方法去结束广播,第二次调用就会抛这个错,你不能关闭两次。