如何解决netlink丢包问题

Python030

如何解决netlink丢包问题,第1张

首先排除各种外在因素,比如猫、路由器、连接线等的设备问题和欠费与否的问题,然后如果你用了路由器而且还是无线路由器,就需要按照说明书重新设置。 建议您办理电信宽带,稳定,故障低,优惠多。

Cgo 使得Go程序能够调用C代码. cgo读入一个用特别的格式写的Go语言文件, 输出Go和C程序, 使得C程序能打包到Go语言的程序包中.

举例说明一下. 下面是一个Go语言包, 包含了两个函数 -- Random 和 Seed -- 是C语言库中random和srandom函数的马甲.

package rand

/*

#include <stdlib.h>

*/ import "C" func Random() int {return int(C.random()) } func Seed(i int) {C.srandom(C.uint(i)) }

我们来看一下这里都有什么内容. 开始是一个包的导入语句.

rand包导入了"C"包, 但你会发现在Go的标准库里没有这个包. 那是因为C是一个"伪包", 一个为cgo引入的特殊的包名, 它是C命名空间的一个引用.

rand 包包含4个到C包的引用: 调用 C.random和C.srandom, 类型转换 C.uint(i)还有引用语句.

Random函数调用libc中的random函数, 然后回返结果. 在C中, random返回一个C类型的长整形值, cgo把它轮换为C.long. 这个值必需转换成Go的类型, 才能在Go程序中使用. 使用一个常见的Go类型转换:

func Random() int {return int(C.random()) }

这是一个等价的函数, 使用了一个临时变量来进行类型转换:

func Random() int {var r C.long = C.random() return int(r) }

Seed函数则相反. 它接受一个Go语言的int类型, 转换成C语言的unsigned int类型, 然后传递给C的srandom函数.

func Seed(i int) {C.srandom(C.uint(i)) }

需要注意的是, cgo中的unsigned int类型写为C.uintcgo的文档中有完整的类型列表.

这个例子中还有一个细节我们没有说到, 那就是导入语句上面的注释.

/*

#include <stdlib.h>

*/ import "C"

Cgo可以识别这个注释, 并在编译C语言程序的时候将它当作一个头文件来处理. 在这个例子中, 它只是一个include语句, 然而其实它可以是使用有效的C语言代码. 这个注释必需紧靠在import "C"这个语句的上面, 不能有空行, 就像是文档注释一样.

Strings and things

与Go语言不同, C语言中没有显式的字符串类型. 字符串在C语言中是一个以0结尾的字符数组.

Go和C语言中的字符串转换是通过C.CString, C.GoString,和C.GoStringN这些函数进行的. 这些转换将得到字符串类型的一个副本.

下一个例子是实现一个Print函数, 它使用C标准库中的fputs函数把一个字符串写到标准输出上:

package print // #include <stdio.h>// #include <stdlib.h>import "C" import "unsafe" func Print(s string) {cs := C.CString(s) C.fputs(cs, (*C.FILE)(C.stdout)) C.free(unsafe.Pointer(cs)) }

在C程序中进行的内存分配是不能被Go语言的内存管理器感知的. 当你使用C.CString创建一个C字符串时(或者其它类型的C语言内存分配), 你必需记得在使用完后用C.free来释放它.

调用C.CString将返回一个指向字符数组开始处的指错, 所以在函数退出前我们把它转换成一个unsafe.Pointer(Go中与C的void 等价的东西), 使用C.free来释放分配的内存. 一个惯用法是在分配内存后紧跟一个defer(特别是当这段代码比较复杂的时候), 这样我们就有了下面这个Print函数:

func Print(s string) {cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) C.fputs(cs, (*C.FILE)(C.stdout)) }

构建 cgo 包

如果你使用goinstall, 构建cgo包就比较容易了, 只要调用像平常一样使用goinstall命令, 它就能自动识别这个特殊的import "C", 然后自动使用cgo来编译这些文件.

如果你想使用Go的Makefiles来构建, 那在CGOFILES变量中列出那些要用cgo处理的文件, 就像GOFILES变量包含一般的Go源文件一样.

rand包的Makefile可以写成下面这样:

include $(GOROOT)/src/Make.inc

TARG=goblog/rand

CGOFILES=\ rand.go\ include $(GOROOT)/src/Make.pkg

然后输入gomake开始构建.

更多 cgo 的资源

cgo的文档中包含了关于C伪包的更多详细的说明, 以及构建过程. Go代码树中的cgo的例子给出了更多更高级的用法.

一个简单而又符合Go惯用法的基于cgo的包是Russ Cox写的gosqlite. 而Go语言的网站上也列出了更多的的cgo包.

最后, 如果你对于cgo的内部是怎么运作这个事情感到好奇的话, 去看看运行时包的cgocall.c文件的注释吧.

不知道你的winsock 是udp还是tcpip协议

这里给你一个我写的实例 我是用的udp 这个发送了一段数据不一定接收就正确 所以我做了校验

'以下是发送文件的

Option Explicit

Dim GetFileNum As Integer, LenFile As Long, SendByte() As Byte '发送的包

Private Sub Command1_Click()

On Error Resume Next

Command1.Enabled = False

GetFileNum = FreeFile '取得未使用的文件号

LenFile = FileLen(Text1.Text) '获得需传送的文件的长度

If Text2.Text = "" Or Right(Left(Text2.Text, 2), 1) <> ":" Then Text2.Text = Text1.Text

Winsock0.SendData "#SEND STA#" & LenFile & "//" & Text2.Text

Wt 0.5

Open Text1.Text For Binary As #GetFileNum '打开需传送的文件

Call TCPSendFile(Winsock0, GetFileNum, SplitFile) '传送文件

Me.Caption = Now

Ti.Enabled = True

End Sub

Private Sub Command2_Click()

Unload Me

End Sub

Private Sub Form_Load()

Dim A As String

On Error Resume Next

Command2.Top = -2000

Winsock0.RemoteHost = IPX '服务器ip

Winsock0.RemotePort = FilePort

End Sub

Private Function SplitFile() As Long '拆包'为了清晰,下面分别用两个子过程来完成计算这次还可以传多少个字节的数据和传送数据

On Error Resume Next

Dim GetCount As Long

If LenFile >= 4000 Then '计算出这次可发送的字节数

  GetCount = 4000

  LenFile = LenFile - GetCount

Else

  GetCount = LenFile

  LenFile = LenFile - GetCount

End If

SplitFile = GetCount

End Function

Private Sub TCPSendFile(objWinSock As Winsock, FileNumber As Integer, SendLen As Long)

On Error Resume Next

Dim FileByte() As Byte, I As Long, j As Long, Temp As String * 4

ReDim SendByte(0)

ReDim FileByte(SendLen - 1)

Temp = SendLen + 7

SendByte = Temp '把长度负值给包头

Get #FileNumber, , FileByte '读取文件

ReDim Preserve SendByte(SendLen + 7) '把包头+到文件头

For I = 0 To UBound(FileByte)

  SendByte(I + 7) = FileByte(I)

  'DoEvents

Next

Winsock0.SendData SendByte

End Sub

Private Sub Form_Unload(Cancel As Integer)

On Error Resume Next

Winsock0.Close

Err.Clear

End Sub

Private Sub TEnd_Timer()

On Error Resume Next

Winsock0.SendData "#END#"

Err.Clear

End Sub

Private Sub Ti_Timer()

On Error Resume Next

Winsock0.SendData "#ERR#"

End Sub

Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)

On Error Resume Next

Dim S As String

Winsock0.GetData S

Select Case S

Case "ok" '成功继续发送

  If LenFile = 0 Then '发送完成

      If S <> "#SEND END#" Then Winsock0.SendData "#SEND END#"

      Me.Caption = "文件上传成功!"

      Command1.Enabled = True

      Ti.Enabled = False

      TEnd.Enabled = True

      Exit Sub

  Else

      Me.Caption = "文件上传完成:[" & Left((FileLen(Text1.Text) - LenFile) / FileLen(Text1.Text) * 100, 4) & "%]"

  End If

  Call TCPSendFile(Winsock0, GetFileNum, SplitFile)

Case "#END#"

  TEnd.Enabled = False

  FMain.TiF.Enabled = True

Case "no" '不成功重发上一个包

  Winsock0.SendData SendByte

End Select

End Sub

'以下是接收文件的

Option Explicit

Dim FOK As Boolean, Fs As Long, FileNumber As Integer, LenFile As Long  '文件的长度

Private Sub Command1_Click()

Unload Me

End Sub

Private Sub Command2_Click()

On Error Resume Next

Dim A As String

Me.Caption = "开始下载"

If Dir(Text2.Text) <> "" And ChV.Value = 0 Then

  If MsgBox("文件已经存在,覆盖吗?", vbCritical + vbYesNo) = vbYes Then Kill Text2.Text Else Exit Sub

Else

  Kill Text2.Text

End If

If Text2.Text = "" Then Text2.Text = Text1.Text

'Command2.Enabled = False

If Ch.Value = 0 Then A = "#DOW#" Else A = "#DOV#"

FMain.Wsk.SendData A & Text1.Text

Wt 1

FMain.Wsk.SendData "#DOE#" & Text2.Text

End Sub

Private Sub Form_Load()

Dim A As String

'FMain.Ts.Enabled = True

On Error Resume Next

If FMain.Cb.Text = "本地组" Or FMain.Cb.Text = "全部组" Then

  Me.Caption = "请重选下载用户[“组”不能正确下载]"

Else

  Command1.Top = -2000

  Winsock0.LocalPort = FilePort

  Winsock0.Bind

End If

End Sub

Private Sub Form_Unload(Cancel As Integer)

On Error Resume Next

Winsock0.Close

Err.Clear

End Sub

Private Sub La_Click()

CDL.FileName = ""

CDL.ShowOpen

Text2.Text = CDL.FileName

End Sub

Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)

On Error Resume Next

Dim FileByte() As Byte, A As String, MendByte() As Byte, I As Long, J As Long, Temp As String, W As String

Winsock0.GetData FileByte, vbArray + vbByte '接收类型为:字节数组

J = UBound(FileByte) '获得包长

For I = 0 To 7 Step 2 '合并包头

  Temp = Temp & Chr(FileByte(I))

Next

For I = 0 To 9 '文件发送结束标记

  A = A & Chr(FileByte(I))

Next

If A = "#ERR#" Then Winsock0.SendData "no"

If A = "#END#" Then

  For I = 0 To Len(FMain.TIn.Text)

      If I < 100 Then

          W = Left(Right(FMain.TIn.Text, I), 1)

          If W = "!" Then

              W = Left(Right(FMain.TIn.Text, I + 4), 5)

              Exit For

          End If

      Else

          Exit For

      End If

  Next I

  If W <> "下载完成!" Then

      FOK = False

      Me.Caption = "下载完成![" & Text2.Text & "]"

      FMain.TIn.Text = FMain.TIn.Text & "[" & Now & "]" & "下载完成!(" & Fs & "<=" & LenFile & ")" & vbCrLf

      Command2.Enabled = True

  End If

Else

  If Val(Temp) = J Then '比较长度看丢包没有

      ReDim MendByte(J - 8)

      For I = 0 To J - 8 '提出包头

          MendByte(I) = FileByte(I + 7)

      Next

      Fs = Fs + UBound(FileByte) - 7

      Put #FileNumber, , MendByte '写文件

      Winsock0.SendData "ok" '发送继续发送的请求

      Me.Caption = "文件下载完成:[" & Left(Fs / LenFile * 100, 4) & "%]"

  Else

      If Left(A, 10) = "#SEND STA#" Then

          A = ""

          For I = 10 To UBound(FileByte) '文件发送结束标记

              A = A & Chr(FileByte(I))

          Next

          LenFile = Val(Left(A, InStr(A, "//") - 1))

          For I = 0 To Len(Text2.Text)

              A = Left(Right(Text2.Text, I), 1)

              If A = "\" Then Exit For

          Next

          If Dir(Left(Text2.Text, Len(Text2.Text) - I + 1), vbDirectory) = "" Then MkDir Left(Text2.Text, Len(Text2.Text) - I + 1)

          '"#SEND STA#" & FileLen(Text1.Text) & "//" & Text2.Text

          FileNumber = FreeFile '取得未使用的文件号

          Fs = 0

          Open Text2.Text For Binary As #FileNumber '打开文件

      Else

          If A <> "#SEND END#" Then

              Winsock0.SendData "no" '出现丢包,请求重发

          Else

              Winsock0.SendData "#END#" '发送继续发送的请求

              Close #FileNumber

              Reset

              If FOK = False Then

                  FOK = True

                  Me.Caption = "下载完成![" & Text2.Text & "]"

                  FMain.TIn.Text = FMain.TIn.Text & "[" & Now & "]" & "下载完成!(" & Fs & "<=" & LenFile & ")" & vbCrLf

                  Command2.Enabled = True

              Else

                  FOK = False

              End If

          End If

      End If

  End If

End If

End Sub