外部IP如何发UDP包到内部IP?有没有类似的相关文章

wolft 2003-08-29 08:02:27
知道QQ\MSN是如何实现的吗,有没有类似的相关文章。
谢谢!
...全文
75 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
l_clove 2003-12-04
  • 打赏
  • 举报
回复
QQ怎么做的?
服务器上哪有代理阿。
顾君彦 2003-12-04
  • 打赏
  • 举报
回复
内部IP需要在代理上使用端口映射或使用socks协议与代理服务器协商解决端口映射问题.
顾君彦 2003-12-04
  • 打赏
  • 举报
回复
qq的通信方式应该是这样的(猜的)
若没有外部IP地址,目前QQ至少可以支持socks协议或者通过网关进行向外连接.
socks协议就不用说了,客户机可以通过支持socks协议的代理服务器协商端口映射的问题.
接着把协商结果送到QQ服务器上.消息就是通过socks映射的端口再由socks服务器转发到内网的.
网关协议可能完成两个网络之间的数据转发.当然能进能出了,但是,向外的表现,也和socks服务器差不多.实现的也是一个端口映射的功能.
shinyblue 2003-11-04
  • 打赏
  • 举报
回复
继续前面的例子程序:

Private WithEvents MyUDPServer As UDPServer
Private MySender As Socket

Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
Dim IPHostInfo As IPHostEntry
Dim i As Integer

MyUDPServer = New UDPServer(IPAddress.Any)
MyUDPServer.OnStart()

btnStart.Enabled = False
btnStop.Enabled = True
btnSend.Enabled = True
End Sub

Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click

Dim lep As New IPEndPoint(IPAddress.Parse(Mid(cboSourceIP.Text, 1, InStr(cboSourceIP.Text, ":") - 1)), Mid(cboSourceIP.Text, InStr(cboSourceIP.Text, ":") + 1))
Dim msg As Byte() = Encoding.Unicode.GetBytes(txtSend.Text)
If MyUDPServer Is Nothing Then Exit Sub
'MySender.SendTo(msg, 0, msg.Length, SocketFlags.None, lep)
MyUDPServer.Send(msg, lep)
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

MySender = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
MySender.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1)

End Sub

Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
Dim i As Integer

MyUDPServer.OnStop()
btnStop.Enabled = False
btnSend.Enabled = False
btnStart.Enabled = True

End Sub

Private Sub MyUDPServer_ReceivedInfo(ByVal Info As String, ByVal SourceIP As String, ByVal SourcePort As Integer) Handles MyUDPServer.ReceivedInfo
Dim Index As Integer

Index = cboSourceIP.FindString(SourceIP)
If Index = -1 Then
cboSourceIP.SelectedIndex = cboSourceIP.Items.Add(SourceIP + ":" + Trim(Str(SourcePort)))
Else
cboSourceIP.SelectedIndex = Index
End If
txtReceiveInfo.AppendText(TimeString + ": " + Info)
txtReceiveInfo.AppendText(vbCrLf)
End Sub
End Class

Public Class UDPServer

Public Event ReceivedInfo(ByVal Info As String, ByVal SourceIP As String, ByVal SourcePort As Integer)



'运行侦听的线程
Private MyListenThread As System.Threading.Thread
'标识线程是否在运行
Private ListenThreadUsed As Boolean
'用于线程同步的通信
Private AllDone As New System.Threading.ManualResetEvent(False)
'侦听Socket
Private MyListen As Socket
'在定义侦听Socket时使用的相关对象
Private IPHostInfo As IPHostEntry
Private MyIPAddress As IPAddress
Private LocalEndPoint As IPEndPoint

'Socket端口号
Private UserPort As Integer = 2061 '用以发送和接收的UDP端口

Private Const MAXMSGLEN = 512 '定义的最大数组长度
Private Const MYMSGLEN = 256 '定义的最大接收长度

Private RecBuffer(MAXMSGLEN) As Byte
Private SendBuffer(MAXMSGLEN) As Byte

Public Sub OnStart()
Dim i As Integer

MyListenThread.Start()

End Sub

Public Sub OnStop()
Dim i As Integer

Try
AllDone.Set()
'终止侦听线程
MyListenThread.Abort()
Do While ListenThreadUsed
If (MyListenThread.ThreadState And Threading.ThreadState.Stopped) = Threading.ThreadState.Stopped Then
ListenThreadUsed = False
End If
Loop
MyListenThread = Nothing

'关闭侦听Socket
MyListen.Close()

'终止所有的连接
'For i = 0 To MySockets.Length - 1
' If Not (MySockets(i).WorkSocket Is Nothing) Then
' If MySockets(i).WorkSocket.Connected Then MySockets(i).WorkSocket.Close()
' MySockets(i).Used = False
' End If
'Next

Catch ex As SocketException
MyListen = Nothing
ListenThreadUsed = False
For i = 0 To MySockets.Length - 1
MySockets(i).WorkSocket = Nothing
MySockets(i).Used = False
Next
MyListenThread = Nothing
End Try
End Sub

'侦听Socket的线程过程
Private Sub Listen()
Dim Sender As New IPEndPoint(IPAddress.Any, 36801)
Dim TempRemoteEP As EndPoint = CType(Sender, EndPoint)

ListenThreadUsed = True

Try
MyListen.Bind(LocalEndPoint)

While True
If (MyListen Is Nothing) Then
Exit While
End If
AllDone.Reset()
'开始响应异步连接
MyListen.BeginReceiveFrom(RecBuffer, 0, RecBuffer.Length, SocketFlags.None, TempRemoteEP, New AsyncCallback(AddressOf ReadCallback), MyListen)
'阻塞并等待信号
AllDone.WaitOne()
End While

Catch e As SocketException
Debug.WriteLine(e.ToString)
'MyListen = Nothing
'ListenThreadUsed = False
Catch e As ObjectDisposedException
Debug.WriteLine(e.ToString)
'MyListen = Nothing
'ListenThreadUsed = False
End Try

ListenThreadUsed = False

End Sub

'接收到客户端数据时的回调函数
Private Sub ReadCallback(ByVal ar As IAsyncResult)
Dim WorkSocket As Socket = CType(ar.AsyncState, Socket)
Dim i As Integer
Dim TempPassword(10) As Byte
Dim Sender As New IPEndPoint(IPAddress.Any, 0)
Dim TempRemoteEP As EndPoint = CType(Sender, EndPoint)
Dim RecString As String

Try
AllDone.Set()
Dim Handler As Socket = WorkSocket
Dim BytesRead As Integer = Handler.EndReceiveFrom(ar, TempRemoteEP)
Sender = TempRemoteEP
Dim BytesLen As Integer

'当接收到数据时,触发事件 ReceiveInfo
If BytesRead > 0 Then

RecString = Encoding.Unicode.GetString(RecBuffer)
RaiseEvent ReceivedInfo(RecString, Sender.Address.ToString, Sender.Port)

End If

Catch ex As ObjectDisposedException
Debug.WriteLine(ex.ToString)

Catch ex As Exception
Debug.WriteLine(ex.ToString)
End Try

RecBuffer.Clear(RecBuffer, 0, RecBuffer.Length)

End Sub

'发送Socket数据
Public Sub Send(ByVal Data() As Byte, ByVal IPPoint As IPEndPoint)
Dim i, j As Integer

AllDone.Reset()
MyListen.BeginSendTo(Data, 0, Data.Length, SocketFlags.None, IPPoint, New AsyncCallback(AddressOf Me.SendCallback), MyListen)
AllDone.WaitOne()

End Sub

'发送Socket数据时的回调函数
Private Sub SendCallback(ByVal ar As IAsyncResult)
Dim Handler As Socket = CType(ar.AsyncState, Socket)
Dim BytesSent As Integer = Handler.EndSendTo(ar)
AllDone.Set()

End Sub

Public Sub New(ByVal IPAdd As IPAddress)
'创建Socket侦听线程
MyListen = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
MyListen.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1)
MyListenThread = New System.Threading.Thread(AddressOf Me.Listen)
MyListenThread.Name = "MyListenThread"
'创建侦听Socket
LocalEndPoint = New IPEndPoint(IPAdd, UserPort)
End Sub
End Class
shinyblue 2003-11-04
  • 打赏
  • 举报
回复
下面是我在.NET下编写的UDP连接的例子,现在有个关键问题,当客户端不知道服务端的IP地址时我不知道该怎么做,在公网上测试时,使用广播IP地址没有任何作用,有待解决。

此程序运行时,客户端和服务端使用同一程序,首先客户端知道服务端IP,然后向服务端的侦听端口2061发送数据,当服务端得到客户端的消息后,在消息来源计算机中选择相应的客户端,然后对客户端进行发送,发送端口号是即时从来源消息中得到的,而不是发送时的端口号2061,好了,现在服务端可以和客户端正常通讯了。

程序用VB.NET2003编写

Imports System.Net
Imports System.Net.Sockets
Imports System.Text

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows 窗体设计器生成的代码 "

Public Sub New()
MyBase.New()

'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()

'在 InitializeComponent() 调用之后添加任何初始化

End Sub

'窗体重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Windows 窗体设计器所必需的
Private components As System.ComponentModel.IContainer

'注意: 以下过程是 Windows 窗体设计器所必需的
'可以使用 Windows 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
Friend WithEvents txtReceiveInfo As System.Windows.Forms.TextBox
Friend WithEvents btnStart As System.Windows.Forms.Button
Friend WithEvents btnStop As System.Windows.Forms.Button
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents btnSend As System.Windows.Forms.Button
Friend WithEvents txtSend As System.Windows.Forms.TextBox
Friend WithEvents cboSourceIP As System.Windows.Forms.ComboBox
Friend WithEvents Label2 As System.Windows.Forms.Label
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.txtReceiveInfo = New System.Windows.Forms.TextBox
Me.btnStart = New System.Windows.Forms.Button
Me.btnStop = New System.Windows.Forms.Button
Me.Label1 = New System.Windows.Forms.Label
Me.btnSend = New System.Windows.Forms.Button
Me.txtSend = New System.Windows.Forms.TextBox
Me.cboSourceIP = New System.Windows.Forms.ComboBox
Me.Label2 = New System.Windows.Forms.Label
Me.SuspendLayout()
'
'txtReceiveInfo
'
Me.txtReceiveInfo.Location = New System.Drawing.Point(16, 32)
Me.txtReceiveInfo.Multiline = True
Me.txtReceiveInfo.Name = "txtReceiveInfo"
Me.txtReceiveInfo.ReadOnly = True
Me.txtReceiveInfo.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
Me.txtReceiveInfo.Size = New System.Drawing.Size(264, 184)
Me.txtReceiveInfo.TabIndex = 5
Me.txtReceiveInfo.Text = ""
Me.txtReceiveInfo.WordWrap = False
'
'btnStart
'
Me.btnStart.Location = New System.Drawing.Point(17, 240)
Me.btnStart.Name = "btnStart"
Me.btnStart.TabIndex = 2
Me.btnStart.Text = "启动接收"
'
'btnStop
'
Me.btnStop.Enabled = False
Me.btnStop.Location = New System.Drawing.Point(104, 240)
Me.btnStop.Name = "btnStop"
Me.btnStop.TabIndex = 3
Me.btnStop.Text = "停止接收"
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(16, 8)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(100, 16)
Me.Label1.TabIndex = 6
Me.Label1.Text = "接收到的消息:"
'
'btnSend
'
Me.btnSend.Enabled = False
Me.btnSend.Location = New System.Drawing.Point(290, 241)
Me.btnSend.Name = "btnSend"
Me.btnSend.TabIndex = 1
Me.btnSend.Text = "发送"
'
'txtSend
'
Me.txtSend.Location = New System.Drawing.Point(289, 195)
Me.txtSend.Name = "txtSend"
Me.txtSend.Size = New System.Drawing.Size(156, 21)
Me.txtSend.TabIndex = 0
Me.txtSend.Text = ""
'
'cboSourceIP
'
Me.cboSourceIP.Location = New System.Drawing.Point(288, 32)
Me.cboSourceIP.Name = "cboSourceIP"
Me.cboSourceIP.Size = New System.Drawing.Size(160, 20)
Me.cboSourceIP.TabIndex = 4
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(288, 8)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(104, 16)
Me.Label2.TabIndex = 7
Me.Label2.Text = "消息来源计算机:"
'
'Form1
'
Me.AcceptButton = Me.btnSend
Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
Me.ClientSize = New System.Drawing.Size(451, 273)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.cboSourceIP)
Me.Controls.Add(Me.txtSend)
Me.Controls.Add(Me.btnSend)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.btnStop)
Me.Controls.Add(Me.btnStart)
Me.Controls.Add(Me.txtReceiveInfo)
Me.Name = "Form1"
Me.Text = "测试UDP-SSL"
Me.ResumeLayout(False)

End Sub

#End Region

shangerhe 2003-10-31
  • 打赏
  • 举报
回复
ding
lance 2003-10-31
  • 打赏
  • 举报
回复
gz
shinyblue 2003-10-31
  • 打赏
  • 举报
回复
用TCP连接,外网作为Server,内网作为Client
laserman 2003-09-11
  • 打赏
  • 举报
回复
tcp外网不能连内网吧
lance 2003-08-29
  • 打赏
  • 举报
回复
gz
wolft 2003-08-29
  • 打赏
  • 举报
回复
这个用C#写的例子很好,但是它并没有解决从外网可以发到内网的问题啊?!
而且还是TCP连接的。。。。。。。。。。
雪狼1234567 2003-08-29
  • 打赏
  • 举报
回复
你可以参考一下这些p2p的例子:

http://www.csharphelp.com/archives/archive261.html

C#下用P2P技术实现点对点聊天
http://developer.ccidnet.com/pub/disp/Article?columnID=340&articleID=27300&pageNO=1
雪狼1234567 2003-08-29
  • 打赏
  • 举报
回复
http://cosoft.org.cn/projects/myicq
雪狼1234567 2003-08-29
  • 打赏
  • 举报
回复
http://www.hypothetic.org/docs/msn/resources/projects.php

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧