`

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版) .doc P2P的简单示例(VB.net版) .doc P2P的简单示例(VB.net版) .doc

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

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

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

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

    FTKernelAPI BT协议内核库及示例源码

    FTKernelAPI BT协议内核库以及示例源码 BitZam 的出现,使BT软件开发不再高深。只要你愿意,不必关心网络编程,BT协议,只需简单的调用FTKernelAPI的接口在3天的时间里就能开发出满足你自己需要的BT下载软件。假如你...

    Visual C++ 2005入门经典--源代码及课后练习答案

    CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《Visual C++ 2005... 11.2.3 简单的Windows程序 598 11.3 Windows程序的组织 600 11.4 MFC 601 ...

    vc++ 开发实例源码包

    OPENG开发的示例代码c++版 演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology 文档。 P2P视频技术源码(含开发文档) 目前的协议有如下一些特点: 1) 客户向服务器发送请求,...

    java源码包2

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包---java 源码 大量 实例

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    JAVA上百实例源码以及开源项目源代码

    Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...

    java源码包3

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包4

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    vc++ 应用源码包_6

    p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...

    vc++ 应用源码包_1

    p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...

    vc++ 应用源码包_5

    p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...

    vc++ 应用源码包_3

    p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...

    vc++ 应用源码包_2

    p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

Global site tag (gtag.js) - Google Analytics