`

P2P的简单示例:VB.net版

 
阅读更多

这是用VB.net实现的一个简单的P2P示例.利用了UDP打洞技术.分服务器端跟客户端.服务器端负责登陆记录用户的IP和端口及转发打洞消息.(相关技术在CSDN搜一下.有很多的.).原理到处都有,这里就没有贴出来.这里贴出了VB.net的代码.供初学者交流.也欢迎高手点评...

服务器端在启动成功后.输入help可以查看到服务器相关命令.

客户端在登陆成功后.输入help可以查看客户端相关命令.(登陆时用户名随便.)

以下是服务器端:

ImportsSystem.Net
ImportsSystem.Net.Sockets
ImportsSystem.Text
ImportsSystem.Threading
ImportsSystem.Collections

ModulemyUDPServerModulemyUDPServer

全局变量#Region"全局变量"

DimServerSocketAsNewSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)
DimipepAsIPEndPoint=NewIPEndPoint(IPAddress.Any,11000)

DimhtUserListAsNewHashtable''''用来保存在线用户和用户的"IP和端口"

DimuserName(0)AsString
DimuserIPEP(0)AsIPEndPoint
DimuserTime(0)AsInteger

DimtimerDelegateAsNewTimerCallback(AddressOfonLineTimeOut)

#EndRegion


参数#Region"参数"

''''以下是客户端到服务器端的消息开头
ConstLOGININAsString="10"''''请求登陆的消息|||消息形式:10+自己的用户名
ConstLOGINOUTAsString="11"''''请求登出的消息|||消息形式:11+自己的用户名
ConstGETULISTAsString="12"''''请求获得在线用户列表|||消息形式:12
ConstP2PCONNAsString="13"''''请求P2P连接的消息|||消息形式:13+自己的用户名+|+对方的用户名
ConstHOLDLINEAsString="14"''''保持连接.|||消息开式:14+自己的用户名

''''以下是服务器到客户端的消息开头
ConstHVUSERAsString="20"''''用户名已存在
ConstGETUSERAsString="21"''''在线用户列表|||消息格式:21+用户名+EP
ConstMAKHOLDAsString="22"''''打洞命令|||消息格式:22+IP
ConstLOGINOKAsString="23"''''登陆成功
ConstSERVCLSAsString="24"''''服务器关闭
ConstMSGENDAsString="25"''''消息结束

''''以下是服务器端的命名
ConstEXITPROAsString="EXIT"''''退出命令
ConstSHOWULISTAsString="SHOWUSER"''''显示在线用户
ConstHELPAsString="HELP"''''显示帮助

#EndRegion


方法#Region"方法"

''''主函数,程序入口
SubMain()SubMain()

''''获得服务器的IP地址
DimaddressListAsSystem.Net.IPAddress()=Dns.GetHostByName(Dns.GetHostName()).AddressList
DimServerIPAsIPAddress=addressList(0)

ServerSocket.Bind(ipep)
Console.WriteLine(
"服务器正在启动....")
Console.WriteLine(
"服务器IP:"&ServerIP.ToString&"正在监听"&ipep.Port.ToString&"端口")
DimlistenTHAsNewThread(AddressOflisten)
listenTH.Start()
''''启用监听的线程
Console.WriteLine("服务器启动成功.....")

DimtimerAsNewTimer(timerDelegate,Nothing,0,5000)

DimSVInputAsString
WhileTrue
Console.Write(
"Server>")
SVInput
=Console.ReadLine().ToUpper
SelectCaseSVInput
CaseEXITPRO
listenTH.Abort()
ServerSocket.Close()
ExitSub
CaseSHOWULIST
showUser()
CaseHELP
Console.Write(
"*********************************"&Chr(10)&Chr(13)&"exit:输出当前程序"&Chr(10)&Chr(13)&"showuser:显示当前在线用户例表"&Chr(10)&Chr(13)&"help:显示帮助"&Chr(10)&Chr(13)&"*********************************"&Chr(10)&Chr(13))
CaseElse
Console.WriteLine(
"*********************************"&Chr(10)&Chr(13)&"笨瓜,你输入的不是有效的命令."&Chr(10)&Chr(13)&"*********************************")
EndSelect
EndWhile


EndSub


''''打印在线用户
SubshowUser()SubshowUser()
DimhavaAsBoolean=False
IfuserName.Length<>0Then
DimiAsInteger
Fori=1TouserName.Length-1
IfuserName(i)<>""Then
hava
=True
ExitFor
EndIf
Next
Ifhava=FalseThen
Console.WriteLine(
"*********************************"&Chr(10)&Chr(13)&"当前没有用户在线"&Chr(10)&Chr(13)&"*********************************")
ExitSub
EndIf
Console.WriteLine(
"*********************************")
Fori=1TouserName.Length-1
IfuserName(i)<>""Then
Console.WriteLine(
"用户名:"&userName(i)&"地址:"&userIPEP(i).ToString)
EndIf
Next
Console.WriteLine(
"*********************************")
Else
Console.WriteLine(
"*********************************"&Chr(10)&Chr(13)&"当前没有用户在线"&Chr(10)&Chr(13)&"*********************************")
EndIf
EndSub


''''服务器监听函数
Sublisten()Sublisten()

WhileTrue

Try
DimrecvAsInteger=0
DimdataAs[Byte]()=NewByte(1024){}
DimsenderAsNewIPEndPoint(IPAddress.Any,0)
DimtempRemoteEPAsEndPoint=CType(sender,EndPoint)
recv
=ServerSocket.ReceiveFrom(data,tempRemoteEP)

''''Console.WriteLine(Encoding.Unicode.GetString(data))

DimmsgHeadAsString=Encoding.Unicode.GetString(data,0,4)
SelectCasemsgHead
CaseLOGININ
DimLoginThingAsString=userLogin(data,tempRemoteEP,recv)
IfLoginThing=HVUSERThen
sendMsg(HVUSER,tempRemoteEP)
ElseIfLoginThing=LOGINOKThen
sendMsg(LOGINOK,tempRemoteEP)

EndIf

CaseLOGINOUT
userloginout(data,recv)

CaseGETULIST
DimuserinfoAsString=getUserList()
sendMsg(userinfo,tempRemoteEP)

CaseP2PCONN
questP2PConn(data,recv)

CaseHOLDLINE
holdOnLine(data,recv)
EndSelect

CatcheAsException
''''Console.WriteLine(e.ToString)
EndTry
EndWhile

EndSub


''''转发P2P连接请求
PrivateSubquestP2PConn()SubquestP2PConn(ByValdata()AsByte,ByValrecvAsInteger)

DimrecvStrAsString=Encoding.Unicode.GetString(data,4,recv-4)
Dimsplit()AsString=recvStr.Split("|")

DimfromEPAsIPEndPoint
DimtoEPAsIPEndPoint
DimiAsInteger
Fori=1TouserName.Length-1
IfuserName(i)=split(0)Then
fromEP
=userIPEP(i)
EndIf
IfuserName(i)=split(1)Then
toEP
=userIPEP(i)
EndIf
Next
Dimholdbytes()AsByte=Encoding.Unicode.GetBytes(MAKHOLD&fromEP.ToString)
ServerSocket.SendTo(holdbytes,toEP)
EndSub


''''函数.返回所有在线用户.其格式:用户名+|+用户IPEP+|
PrivateFunctiongetUserList()FunctiongetUserList()AsString
DimuserInfoAsString=GETUSER
DimiAsInteger
Fori=1TouserName.Length-1
IfuserName(i)<>""Then
userInfo
+=userName(i)&"|"&userIPEP(i).ToString&"|"
EndIf
Next
ReturnuserInfo
EndFunction


''''用户登陆,直接返回登陆是否成功的值
PrivateFunctionuserLogin()FunctionuserLogin(ByValdataAsByte(),ByValuserEPAsIPEndPoint,ByValrecvCountAsInteger)AsString

DimUnameAsString=Encoding.Unicode.GetString(data,4,recvCount-4)

DimUinfobytes()AsByte

DimiAsInteger
DimjAsInteger

Fori=1TouserName.Length-1
IfUname=userName(i)Then
ReturnHVUSER
EndIf
Next

Fori=1TouserName.Length-1
IfuserName(i)=""Then
userName(i)
=Uname
userIPEP(i)
=userEP
userTime(i)
=60
Console.Write(
Chr(10)&Chr(13)&"*********************************"&Chr(10)&Chr(13)&Uname.Trim&"上线了."&"用户地址:"&userEP.ToString&Chr(10)&Chr(13)&"*********************************"&Chr(10)&Chr(13))
Console.Write(
"Server>")

Uinfobytes
=Encoding.Unicode.GetBytes(LOGININ&userName(i)&"|"&userIPEP(i).ToString)

Forj=1TouserName.Length-1
IfuserName(j)<>""AnduserName(j)<>UnameThen
ServerSocket.SendTo(Uinfobytes,userIPEP(j))
EndIf
Next
ReturnLOGINOK
EndIf
Next

DimuserCountAsInteger=userName.Length

ReDimPreserveuserName(userCount)
ReDimPreserveuserIPEP(userCount)
ReDimPreserveuserTime(userCount)

userName(userName.Length
-1)=Uname
userIPEP(userIPEP.Length
-1)=userEP
userTime(userTime.Length
-1)=60

Console.Write(
Chr(10)&Chr(13)&"*********************************"&Chr(10)&Chr(13)&Uname.Trim&"上线了."&"用户地址:"&userEP.ToString&Chr(10)&Chr(13)&"*********************************"&Chr(10)&Chr(13))
Console.Write(
"Server>")

Uinfobytes
=Encoding.Unicode.GetBytes(LOGININ&userName(userName.Length-1)&"|"&userIPEP(userName.Length-1).ToString)

Forj=1TouserName.Length-1
IfuserName(j)<>""AnduserName(j)<>UnameThen
ServerSocket.SendTo(Uinfobytes,userIPEP(j))
EndIf
Next
ReturnLOGINOK

EndFunction


''''用户登出
PrivateSubuserloginout()Subuserloginout(ByValdataAsByte(),ByValrecvCountAsInteger)

DimiAsInteger
DimUnameAsString=Encoding.Unicode.GetString(data,4,recvCount-4)

Fori=1TouserName.Length-1

IfUname=userName(i)Then

DimloginOutMsgAsString=LOGINOUT&userName(i)


userName(i)
=""
userIPEP(i)
=Nothing
userTime(i)
=0

DimjAsInteger
Forj=1TouserName.Length-1
IfuserName(j)<>""Then

sendMsg(loginOutMsg,userIPEP(j))

EndIf
Next

Console.WriteLine(
Chr(10)&Chr(13)&"*********************************")
Console.WriteLine(
"用户"&Uname&"下线了.")
Console.WriteLine(
"*********************************")
Console.Write(
"Server>")

ExitFor

EndIf

Next

EndSub


''''保持用户在线的过程
PrivateSubholdOnLine()SubholdOnLine(ByValdataAsByte(),ByValrecvCountAsInteger)

DimUnameAsString=Encoding.Unicode.GetString(data,4,recvCount-4)

DimiAsInteger

Fori=1TouserName.Length-1

IfUname=userName(i)Then

userTime(i)
=60
ExitFor

EndIf

Next

EndSub


''''用户超时退出
PrivateSubonLineTimeOut()SubonLineTimeOut(ByValstateAs[Object])

DimiAsInteger

Fori=1TouserName.Length-1

IfuserTime(i)>0Then

userTime(i)
-=5

IfuserTime(i)<=0Then

DimloginoutmsgAsString=LOGINOUT&userName(i)

Console.WriteLine(
Chr(10)&Chr(13)&"*********************************")
Console.WriteLine(
"用户"&userName(i)&"下线了.")
Console.WriteLine(
"*********************************")
Console.Write(
"Server>")

userName(i)
=""
userIPEP(i)
=Nothing

DimULoginOutbytes()AsByte=Encoding.Unicode.GetBytes(loginoutmsg)

DimjAsInteger
Forj=1TouserName.Length-1

IfuserName(j)<>""Then
IfuserIPEP(j)IsNothingThen
Else
ServerSocket.SendTo(ULoginOutbytes,userIPEP(j))
EndIf
EndIf

Next

EndIf

EndIf

Next

EndSub


''''发送消息的函数
SubsendMsg()SubsendMsg(ByValmsgAsString,ByValremoteEPAsIPEndPoint)
DimsendBytesAs[Byte]()=Encoding.Unicode.GetBytes(msg)
Try

ServerSocket.SendTo(sendBytes,remoteEP)

CatcheAsException
Console.WriteLine(e.ToString())
EndTry
EndSub


#EndRegion


EndModule


以下是客户端:

ImportsSystem.Net
ImportsSystem.Net.Sockets
ImportsSystem.Text
ImportsSystem.Threading


ModuleModule1ModuleModule1

参数#Region"参数"

''''以下是客户端到服务器端的消息开头
ConstLOGININAsString="10"''''请求登陆的消息|||消息形式:10+自己的用户名
ConstLOGINOUTAsString="11"''''请求登出的消息|||消息形式:11+自己的用户名
ConstGETULISTAsString="12"''''请求获得在线用户列表|||消息形式:12+自己的用户名
ConstP2PCONNAsString="13"''''请求P2P连接的消息|||消息形式:13+自己的用户名+对方的用户名
ConstHOLDLINEAsString="14"''''保持连接.|||消息开式:14+自己的用户名

''''以下是服务器到客户端的消息开头
ConstHVUSERAsString="20"''''用户名已存在
ConstGETUSERAsString="21"''''在线用户列表|||消息格式:21+用户名+EP
ConstMAKHOLDAsString="22"''''打洞命令|||消息格式:22+IP
ConstLOGINOKAsString="23"''''登陆成功
ConstSERVCLSAsString="24"''''服务器关闭
ConstMSGENDAsString="25"''''消息结束

''''以下是客户端到客户端的消息开头
ConstHOLDOKAsString="30"''''打洞成功
ConstCHATMSGAsString="31"''''聊天消息
ConstCHTMSGENDAsString="32"''''聊天消息发送成功

''''以下是客户端的命名
ConstEXITPROAsString="EXIT"''''退出命令
ConstSHOWULISTAsString="SHOWUSER"''''显示在线用户
ConstHELPAsString="HELP"''''显示帮助
ConstSENDAsString="SEND"''''发送消息

#EndRegion


全局全量#Region"全局全量"

DelegateSubmyMethodDelegate()SubmyMethodDelegate(ByRefmyInDataAsByte())''''登陆时用的事件

''''DimMaxTryAsInteger=5
DimmsgSendEndAsBoolean=False''''消息是否发送成功,若发送成功,则会返回结束消息
DimThListenAsNewThread(AddressOflisten)''''监听的线程
DimClientSocketAsNewSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)''''客户端套节字的定义
DimusernameAsString''''当前用户名
DimServerEPAsIPEndPoint''''服务器的IPEP
DimholdBytesAs[Byte]()=Encoding.Unicode.GetBytes(HOLDLINE&username)''''和服务器保持连接连接时用到的byte数组
DimOLUserName()AsString
DimOLUserEP()AsIPEndPoint
DimgetUrecCountAsInteger
DimtestHoldAsBoolean=False
DimtestChatAsBoolean=False

PrivatereceiveDoneAsManualResetEvent''''在登陆时用来阻塞线程,等待收到数据
PrivatesendDoneAsManualResetEvent''''用来阴塞发送消息的线程.等待收到回送的确认消息
PrivategetUDoneAsManualResetEvent''''用来阻塞请求好友名单的线程,等待接收好友名单
PrivateholdDoneAsManualResetEvent''''用来阻塞打洞时的线程
PrivatechatDoneAsManualResetEvent''''用来阻塞发送聊天消息时的线程

DimtimerDelegateAsNewTimerCallback(AddressOfholdonline)''''为保持在线状态弄得

#EndRegion


方法#Region"方法"

''''主函数,程序入口
SubMain()SubMain()
DimInputIPAsString
DimInputOKAsBoolean=False


''''判断输入的IP,并且保存服务器的IPEP
WhileInputOK<>True
Console.Write(
"请输入服务器IP:")
InputIP
=Console.ReadLine()
Try
ServerEP
=NewIPEndPoint(IPAddress.Parse(InputIP),11000)
InputOK
=True
Catch
Console.WriteLine(
"你输入的服务器IP不正确,请重新输入.")
InputOK
=False
EndTry
EndWhile

DimboolAsBoolean=False

''''判断用户是否登陆成功
Whilebool<>True

DimLoginOKAsBoolean=Login()
IfLoginOK=TrueThen
bool
=True
Else
Console.Write(
"是否重试:输入Y重试,输入任意值退出程序:")
DimtempYNAsString=Console.ReadLine.ToUpper
IftempYN="Y"Then
bool
=False
Else
ExitSub
EndIf
EndIf

EndWhile

Console.WriteLine(
"用户名:"&username)
holdBytes
=Encoding.Unicode.GetBytes(HOLDLINE&username)
''''登陆成功后.用一个timer,每隔50秒向服务器发送消息,保持在线状态跟在主机注册的端口
DimtimerAsNewTimer(timerDelegate,Nothing,10000,50000)

''''请求在线名单
Console.WriteLine("正在获取在线名单,请稍后....")
DimgetUboolAsBoolean=False
WhilegetUbool<>True
getUbool
=getU()
IfgetUbool=FalseThen
Console.Write(
"是否重试:输入Y重试,输入任意值退出程序:")
DimtempYNAsString=Console.ReadLine.ToUpper
IftempYN="Y"Then
bool
=False
Else
ExitSub
EndIf
EndIf
EndWhile

ThListen.Start()

''''用来处理客户端的一些命令
DimSVInputAsString
WhileTrue
Console.Write(
"Client>")
SVInput
=Console.ReadLine().ToUpper
SelectCaseSVInput
CaseEXITPRO
exitApp()
ThListen.Abort()
ClientSocket.Close()
ExitSub
CaseSHOWULIST
Console.WriteLine(
"*********************************")
showUserList()
Console.WriteLine(
"*********************************")
CaseHELP
Console.Write(
"*********************************"&Chr(10)&Chr(13)&"exit:输出当前程序"&Chr(10)&Chr(13)&"showuser:显示当前在线用户例表"&Chr(10)&Chr(13)&"send:发送消息.格式:send用户名消息"&Chr(10)&Chr(13)&"help:显示帮助"&Chr(10)&Chr(13)&"*********************************"&Chr(10)&Chr(13))
CaseElse
IfSVInput.Substring(0,4)="SEND"Then
Dimsplit()AsString=SVInput.Split("")
Ifsplit.Length=3Then
sendChatMsg(
split(1),split(2))
Else
Console.WriteLine(
"*********************************"&Chr(10)&Chr(13)&"你输入的命令格式不正确.send命令格式为:send用户名你的消息"&Chr(10)&Chr(13)&"*********************************")
EndIf
Else
Console.WriteLine(
"*********************************"&Chr(10)&Chr(13)&"笨瓜,你输入的不是有效的命令."&Chr(10)&Chr(13)&"*********************************")
EndIf
EndSelect
EndWhile

EndSub


''''登陆函数
PrivateFunctionLogin()FunctionLogin()AsBoolean

receiveDone
=NewManualResetEvent(False)
DimuserBytesAs[Byte]()

DimuserOKAsBoolean=False

Console.Write(
"请输入你的用户名:")

''''判断用户名是否符合格式
While(userOK<>True)
username
=Console.ReadLine.ToUpper
userBytes
=Encoding.Unicode.GetBytes(LOGININ&username)

IfuserBytes.Length>24OruserBytes.Length<10Then
Console.WriteLine(
"用户名不得小于6个字节,且不得大于20个字节.")
Console.Write(
"请重新输入你的用户名:")
Else
userOK
=True
EndIf
EndWhile

''''向服务器发送客户消息
ClientSocket.SendTo(userBytes,ServerEP)

DimdataAs[Byte]()=NewByte(1024){}

DimcomStrAsString=Encoding.Unicode.GetString(data,0,4)

''''异面的接收服务器回送的消息
DimDGrecvAsNewmyMethodDelegate(AddressOfrecvLogin)
DGrecv.BeginInvoke(data,
Nothing,Nothing)

''''等待服务器回送消息的时长为10秒,否则为服务器超时
receiveDone.WaitOne(30000,True)

DimrecvStrAsString=Encoding.Unicode.GetString(data,0,4)

IfrecvStr=comStrThen
Console.WriteLine(
"服务器超时.登陆失败!!")
ReturnFalse
EndIf

IfEncoding.Unicode.GetString(data,0,4)=LOGINOKThen
Console.WriteLine(
"登陆成功!!")
ReturnTrue
ElseIfEncoding.Unicode.GetString(data,0,4)=HVUSERThen
Console.WriteLine(
"用户名重复.登陆失败!!")
ReturnFalse
Else
Console.WriteLine(
"服务器未知错误,登陆失败!!")
ReturnFalse
EndIf

EndFunction


''''登出函数
PrivateSubexitApp()SubexitApp()

DimloginOutStrAsString=LOGINOUT&username
DimsendBytesAs[Byte]()=Encoding.Unicode.GetBytes(loginOutStr)
ClientSocket.SendTo(sendBytes,ServerEP)

EndSub


''''请求好友列表的函数
PrivateFunctiongetU()FunctiongetU()AsBoolean

getUDone
=NewManualResetEvent(False)
DimgetUbytesAsByte()=Encoding.Unicode.GetBytes(GETULIST)
ClientSocket.SendTo(getUbytes,ServerEP)

DimdataAs[Byte]()=NewByte(4056){}
DimcomStrAsString=Encoding.Unicode.GetString(data,0,4)

DimGUrecvAsNewmyMethodDelegate(AddressOfrecvGetU)
GUrecv.BeginInvoke(data,
Nothing,Nothing)

getUDone.WaitOne(
30000,True)

DimrecvStrAsString=Encoding.Unicode.GetString(data,0,4)

IfrecvStr=comStrThen
Console.WriteLine(
"服务器超时.或取好友名单失败!!")
ReturnFalse
EndIf

IfEncoding.Unicode.GetString(data,0,4)=GETUSERThen
getUserList(data,getUrecCount)
Console.WriteLine(
"获取在线名单成功!!")
showUserList()
ReturnTrue
Else
Console.WriteLine(
"服务器未知错误,获取在线名单失败!!")
ReturnFalse
EndIf

EndFunction


''''登陆时用来异步的接收服务器发送的消息
SubrecvLogin()SubrecvLogin(ByRefinDataAsByte())

ClientSocket.Receive(inData)
receiveDone.Set()

EndSub


''''请求好友名单时用来异步接收服务器发送的消息
SubrecvGetU()SubrecvGetU(ByRefinDataAsByte())

getUrecCount
=ClientSocket.Receive(inData)
getUDone.Set()

EndSub


''''处理收到的在线用户信息
PrivateSubgetUserList()SubgetUserList(ByValuserInfobytes()AsByte,ByValreccountAsInteger)

DimustrAsString=Encoding.Unicode.GetString(userInfobytes,4,reccount-4)

DimsplitStr()AsString=Nothing

splitStr
=Ustr.Split("|")

DimIPEPSplit()AsString=Nothing

DimiAsInteger=0

DimkAsInteger
Fork=0TosplitStr.Length-2Step2
ReDimPreserveOLUserName(i)
ReDimPreserveOLUserEP(i)

OLUserName(i)
=splitStr(k)
IPEPSplit
=splitStr(k+1).Split(":")
OLUserEP(i)
=NewIPEndPoint(IPAddress.Parse(IPEPSplit(0)),IPEPSplit(1))

IPEPSplit
=Nothing
i
+=1
Next

EndSub


''''显示在线用户
PrivateSubshowUserList()SubshowUserList()
DimiAsInteger
Fori=0ToOLUserName.Length-1
IfOLUserName(i)<>""Then
Console.WriteLine(
"用户名:"&OLUserName(i)&"用户IP:"&OLUserEP(i).ToString)
EndIf
Next
EndSub


''''客户程序监听的函数
Sublisten()Sublisten()

WhileTrue

Try
DimrecvAsInteger=0''''收到的字节数
DimdataAs[Byte]()=NewByte(1024){}''''缓冲区大小
DimsenderAsNewIPEndPoint(IPAddress.Any,0)
DimtempRemoteEPAsEndPoint=CType(sender,EndPoint)
recv
=ClientSocket.ReceiveFrom(data,tempRemoteEP)

DimmsgHeadAsString=Encoding.Unicode.GetString(data,0,4)''''获得消息头的内容
SelectCasemsgHead
CaseMSGEND
msgSendEnd
=True
sendDone.Set()
CaseLOGININ
addOnLine(data,recv)
CaseLOGINOUT
removeOnLine(data,recv)
CaseMSGEND
msgSendEnd
=True
sendDone.Set()
CaseMAKHOLD
Console.WriteLine(
Chr(10)&Chr(13)&"收到打洞消息.")
makeHold(data,recv)
Console.Write(
"Client>")
CaseCHATMSG
showChatMsg(data,recv)
CaseHOLDOK
testHold
=True
holdDone.Set()
CaseCHTMSGEND
testChat
=True
chatDone.Set()
EndSelect

Catch
EndTry

EndWhile
EndSub


''''发送聊天消息
PrivateSubsendChatMsg()SubsendChatMsg(ByValremoteUserAsString,ByValchatMsgStrAsString)

IfremoteUser=usernameThen
Console.WriteLine(
"猪头,你想干什么!!!")
ExitSub
EndIf

DimiAsInteger

DimremoteUEPAsIPEndPoint
Fori=0ToOLUserName.Length-1
IfremoteUser=OLUserName(i)Then
remoteUEP
=OLUserEP(i)
ExitFor
EndIf
Ifi=OLUserName.Length-1Then
Console.WriteLine(
"找不到你想发送的用户.")
ExitSub
EndIf
Next

Dimmsgbytes()AsByte=Encoding.Unicode.GetBytes(CHATMSG&username&"|"&chatMsgStr)
Dimholdbytes()AsByte=Encoding.Unicode.GetBytes(P2PCONN&username&"|"&remoteUser)

chatDone
=NewManualResetEvent(False)
ClientSocket.SendTo(msgbytes,remoteUEP)
chatDone.WaitOne(
10000,True)
IftestChat=TrueThen
testChat
=False
ExitSub
EndIf

testHold
=False
WhiletestHold<>True
Console.WriteLine(
"打洞ing.....")
holdDone
=NewManualResetEvent(False)
ClientSocket.SendTo(holdbytes,remoteUEP)
ClientSocket.SendTo(holdbytes,ServerEP)
holdDone.WaitOne(
10000,True)
IftestHold=TrueThen
ExitWhile
Else
Console.WriteLine(
"打洞超时,发送消息失败.")
Console.Write(
"是否重试,按Y重试,按任意值结束发送:")
DimYorNAsString=Console.ReadLine().ToUpper
IfYorN="Y"Then
testHold
=False
Else
ExitSub
EndIf
EndIf
EndWhile

WhiletestChat<>True
Console.WriteLine(
"打洞成功,正在准备发送.....")
chatDone
=NewManualResetEvent(False)
ClientSocket.SendTo(msgbytes,remoteUEP)
chatDone.WaitOne(
10000,True)
IftestChat=TrueThen
Console.WriteLine(
"消息发送成功!!")
ExitWhile
Else
Console.WriteLine(
"发送超时,发送消息失败.")
Console.Write(
"是否重试,按Y重试,按任意值结束发送:")
DimYorNAsString=Console.ReadLine().ToUpper
IfYorN="Y"Then
testChat
=False
Else
ExitSub
EndIf
EndIf
EndWhile
testHold
=False
testChat
=False
EndSub


''''处理聊天消息
PrivateSubshowChatMsg()SubshowChatMsg(ByValindata()AsByte,ByValrecvcountAsInteger)
DimmsgStrAsString=Encoding.Unicode.GetString(indata,4,recvcount-4)
DimsplitStr()AsString=msgStr.Split("|")
DimfromUnameAsString=splitStr(0)
DimmsgAsString=splitStr(1)
Console.WriteLine(
Chr(10)&Chr(13)&"收到来自"&fromUname&"的消息:"&msg)
Console.Write(
"Client>")
DimiAsInteger
Fori=0ToOLUserName.Length-1
IfOLUserName(i)=fromUnameThen
ExitFor
EndIf
Next
Dimtempbytes()AsByte=Encoding.Unicode.GetBytes(CHTMSGEND)
ClientSocket.SendTo(tempbytes,OLUserEP(i))
EndSub


''''处理打洞函数
PrivateSubmakeHold()SubmakeHold(ByValindata()AsByte,ByValrecvcountAsInteger)
DimmakholdstrAsString=Encoding.Unicode.GetString(indata,4,recvcount)
Dimipepstr()AsString=makholdstr.Split(":")
DimholdEPAsIPEndPoint=NewIPEndPoint(IPAddress.Parse(ipepstr(0)),ipepstr(1))

Dimholdbytes()AsByte=Encoding.Unicode.GetBytes(HOLDOK&username)
ClientSocket.SendTo(holdbytes,holdEP)
Console.WriteLine(
"回送打洞消息.")
EndSub


''''处理用户上线的函数
PrivateSubaddOnLine()SubaddOnLine(ByValinData()AsByte,ByValrecvCountAsInteger)
DiminStrAsString=Encoding.Unicode.GetString(inData,4,recvCount-4)
Dimuserinfo()AsString=inStr.Split("|")
DimstrUserEP()AsString=userinfo(1).Split(":")

DimiAsInteger
Fori=0ToOLUserName.Length-1
IfOLUserName(i)=""Then
OLUserName(i)
=userinfo(0)
OLUserEP(i)
=NewIPEndPoint(IPAddress.Parse(strUserEP(0)),strUserEP(1))
Console.WriteLine(
Chr(10)&Chr(13)&"用户"&OLUserName(i)&"上线了.用户地址:"&OLUserEP(i).ToString)
Console.Write(
"Client>")
ExitSub
EndIf
Next

ReDimPreserveOLUserName(i+1)
ReDimPreserveOLUserEP(i+1)

OLUserName(i
+1)=userinfo(0)
OLUserEP(i
+1)=NewIPEndPoint(IPAddress.Parse(strUserEP(0)),strUserEP(1))

Console.WriteLine(
Chr(10)&Chr(13)&"用户"&OLUserName(i+1)&"上线了.用户地址:"&OLUserEP(i+1).ToString)
Console.Write(
"Client>")

EndSub


''''处理用户下线的函数
PrivateSubremoveOnLine()SubremoveOnLine(ByValinData()AsByte,ByValrecvCountAsInteger)
DimoffUnameAsString=Encoding.Unicode.GetString(inData,4,recvCount-4)

DimiAsInteger
Fori=0ToOLUserName.Length-1
IfOLUserName(i)=offUnameThen
OLUserName(i)
=""
OLUserEP(i)
=Nothing
Console.WriteLine(
Chr(10)&Chr(13)&"用户"&offUname&"下线了.")
Console.Write(
"Client>")
ExitSub
EndIf
Next
EndSub


''''发送消息的函数
PublicFunctionsendmsg()Functionsendmsg(ByValmsgAsString,ByValsendToIPEPAsIPEndPoint)AsString

DimsendBytesAs[Byte]()=Encoding.Unicode.GetBytes(msg)

''''判断发送的字节数是否超过了服务器缓冲区大小
IfsendBytes.Length>1024Then
Return"W输入的字数太多"
EndIf

''''判断消息是否发送成功
WhilemsgSendEnd=False

sendDone
=NewManualResetEvent(False)

Try

ClientSocket.SendTo(sendBytes,sendToIPEP)

sendDone.WaitOne(
10000,True)''''阻塞线程10秒

IfmsgSendEnd=FalseThen
Console.WriteLine(
"消息发送超时")
Else
ExitWhile
EndIf

CatcheAsException

Console.WriteLine(
"发送消息失败"&e.ToString)
ExitFunction

EndTry

Console.Write(
"是否重试?按Y重试,按任意键退出:")
DimuserInputAsString=Console.ReadLine.ToUpper

IfuserInput="Y"Then
Else
msgSendEnd
=False
ExitFunction
EndIf

EndWhile

msgSendEnd
=False

EndFunction


''''用保持在线状态的函数
PrivateSubholdonline()Subholdonline(ByValstateAs[Object])
ClientSocket.SendTo(holdBytes,ServerEP)
EndSub


#EndRegion


EndModule

分享到:
评论

相关推荐

    P2P的简单示例(VB.net版)

    标题 "P2P的简单示例(VB.net版)...总之,创建一个简单的P2P示例需要深入理解网络编程、多线程、数据交换和错误处理等概念,并能熟练运用VB.NET的相关类库。实际项目中,还需要考虑性能优化、网络安全以及兼容性等问题。

    VB.NET代码示例

    本示例主要关注的是利用VB.NET实现TCP协议下的NAT穿透,这是一种在网络通信中非常重要的技术,特别是在P2P(点对点)通讯和远程控制场景下。 首先,TCP(Transmission Control Protocol)是互联网协议栈中的传输层...

    ASP.NET 3.5入门经典--涵盖C#和VB.NET(Wrox)

    书名: ASP.NET 3.5入门经典——涵盖C#和VB.NET(第5版) 丛书名: 作者: (荷兰) Imar Spaanjaars著 这是一本非常好的ASP.NET入门书籍。本书以建立一个实际的Web站点为主线,从最初的没有任何功能的简单站点开始,...

    VB2008 多文件内网传送程序

    【VB2008 多文件内网传送程序】是一个基于TCP协议的文件传输软件,由VB.NET开发,适用于.NET框架。该程序设计简洁,具有良好的用户界面,支持多个窗口进行点对点的文件传输,使得在局域网内的文件共享变得更加方便...

    VB6,测试成功的P2P代码

    描述中提到,作者发现VB6用于P2P穿透的实例非常稀缺,因此他创建了一个示例来帮助其他人理解这一过程。这里的关键点是,为了测试这个P2P系统,你需要三个网络参与:一个服务端和两个客户端,它们分别位于不同的网络...

    Silverlight P2P 经典类库

    "Silverlight"则说明这个类库是专为Silverlight开发环境设计的,可以与XAML、C#或VB.NET等语言无缝集成。"类库"表示这是一个可复用的代码集合,为开发者提供便利的功能模块。 【压缩包子文件的文件名称列表】 1. ...

    vbfileupload_visualbasic_

    标题“vbfileupload_visualbasic_”暗示了这是一个关于使用Visual Basic进行文件上传的教程或示例。在描述中提到的“两个VB点对点发送文件例子”,表明我们将探讨如何使用VB实现TCP/IP协议来实现实时文件传输,这...

    P2P聊天工具 有PPT的 

    开发者可以使用C#、VB.NET或其他.NET支持的语言来编写代码。在P2P聊天工具的上下文中,.NET框架提供了丰富的类库和API,支持网络通信、数据序列化、多线程等关键功能,便于构建这样的应用程序。 【内容概览】 1. *...

    VB在网络传输中的一点代码

    ### VB.NET中的网络点对点传输技术:TCP通信详解 #### 概述 在计算机网络领域,点对点(P2P)传输是一种重要的数据交换方式,它允许两台或多台设备之间直接进行通信,无需通过中央服务器。在Visual Basic (VB) 开发...

    TFTP接收方的列子 用来进行UDP文件传输

    描述中提到的“UDP穿透NAT的列子”,暗示了这个示例可能涉及P2P通信或端口映射技术,因为NAT通常会阻止来自外部网络的直接通信。在NAT环境下,两个内部网络的主机通过公共IP和端口进行通信时,需要一种机制来正确...

    P2P_file_sharing_code.rar_Find Files_VB 文件共享_sharing files

    标题 "P2P_file_sharing_code.rar_Find Files_VB 文件共享_sharing files" 提供了我们讨论的关键点:这是一个基于VB(Visual Basic)编程语言实现的P2P(点对点)文件共享客户端,它的主要功能是让用户能够搜索并...

    vb2005 教程

    VB2005,全称Visual Basic .NET 2005,是微软公司推出的.NET框架下的编程语言版本,主要用于构建Windows桌面应用、Web应用以及移动应用等。本教程是针对初学者的入门资料,旨在帮助新手快速掌握VB2005的基础知识和...

    VB.zip_VB 聊天室 群发_site:www.pudn.com_vb6 聊天_vb6.0 聊天

    这个项目可能是一个学习示例,也可能是一个小型的实际应用,用于在局域网内进行点对点通信。 描述中提到的“基于VB6.0,点对点聊天工具,局域网内可以使用的小程序”进一步细化了该程序的特点。VB6.0是微软推出的一...

    BitTorrent.Net-开源

    6. **兼容性**:由于是.NET框架的一部分,这个库可以与各种.NET语言如C#、VB.NET、F#等无缝配合。 在使用BitTorrent.Net时,开发者需要注意以下几个关键概念: - **Tracker**:BitTorrent网络中的服务器,负责维护...

    VB6.0保持窗体显示在最前面的示例代码

    摘要:VB源码,数据库应用,窗口置顶,显示在最前面 VisualBasic6.0让窗体保持在其它窗体的最前面显示,不被遮挡,目前像一些P2P视频播放软件都广泛加入类似功能,期待与大家共勉,书中的实例,稍加修改,用的可自己...

    msdn for vb

    开发者可能会在这里找到如何使用VB创建聊天应用、实现P2P通信或者集成第三方即时通信SDK的教程和示例。 综上所述,"msdn for vb"这个资源集合可能是VB开发者的一份宝贵财富,包含了一系列关于VB编程、API使用、即时...

    Brian E. Dick-开源

    VB.NET是微软开发的一种面向对象的编程语言,它允许开发者利用.NET框架来创建各种应用程序。这里的“Net API”很可能指的是Windows API(应用程序编程接口),它是操作系统提供的一组函数,供应用程序调用以执行各种...

    VB获取网卡的物理地址

    以下是一个简单的VB代码示例,展示了如何调用WMI来获取MAC地址: ```vb Imports System.Management Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ...

    WebRTCDemo-master_android-studio

    这个“WebRTCDemo-master_android-studio”项目显然是一个基于Android Studio的WebRTC示例应用,用于演示如何在Android设备上实现P2P(对等网络)视频和音频通信。 1. **WebRTC基础**:WebRTC提供了音频、视频和...

Global site tag (gtag.js) - Google Analytics