- 浏览: 1145901 次
- 性别:
- 来自: nibiru
文章分类
- 全部博客 (407)
- lucene (1)
- java (147)
- j2se (1)
- javascript (2)
- spring (5)
- hibernate (1)
- mysql (1)
- oracle (10)
- 工作 (10)
- JPA (13)
- 网站 (5)
- xml (2)
- mina (3)
- 思想 (16)
- httpclient (10)
- JFreeChart (1)
- 多线程 (0)
- swing (2)
- socket (0)
- 网络 (3)
- protocol buffer (0)
- jmx (2)
- jboss/weblogic (1)
- flex3 (12)
- 设计模式 (1)
- apache (0)
- php (4)
- struts1&2 (2)
- oracle SOA (2)
- 微博短链接的生成算法(Java版本) (1)
- htmlparser (3)
- quartz (2)
- mail (1)
- 乱码 (2)
- txt (1)
- eclipse (7)
- 分类 (0)
- 数据库 (1)
- svn (1)
- 日志 (1)
- struts2 (4)
- jquery (2)
- 编码 (1)
- 路径,java (1)
- SOHO (1)
- 娱乐 (2)
- frameset (1)
- maven (1)
- 反射 (1)
- truts2 (1)
- 敏捷,scrum (1)
- OA (1)
- english (1)
- oralce (1)
- wampserver (1)
- 会计 (1)
- springmvc (1)
- js (1)
- CMA (1)
最新评论
-
ludabing:
[/color][color=yellow]
spring @component的作用 -
netwelfare:
EL表达式中null和empty的区别,可以看这篇文章:htt ...
EL表达式中empty的用法 -
wjs王结胜:
...
spring @component的作用 -
di1984HIT:
哈哈。真不错啊。~
微博短链接的生成算法(Java版本) -
di1984HIT:
不错,不错。。。
spring @component的作用
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
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版) .doc P2P的简单示例(VB.net版) .doc P2P的简单示例(VB.net版) .doc
书名: ASP.NET 3.5入门经典——涵盖C#和VB.NET(第5版) 丛书名: 作者: (荷兰) Imar Spaanjaars著 这是一本非常好的ASP.NET入门书籍。本书以建立一个实际的Web站点为主线,从最初的没有任何功能的简单站点开始,...
摘要:VB源码,数据库应用,窗口置顶,显示在最前面 VisualBasic6.0让窗体保持在其它窗体的最前面显示,不被遮挡,目前像一些P2P视频播放软件都广泛加入类似功能,期待与大家共勉,书中的实例,稍加修改,用的可自己...
FTKernelAPI BT协议内核库以及示例源码 BitZam 的出现,使BT软件开发不再高深。只要你愿意,不必关心网络编程,BT协议,只需简单的调用FTKernelAPI的接口在3天的时间里就能开发出满足你自己需要的BT下载软件。假如你...
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 ...
OPENG开发的示例代码c++版 演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology 文档。 P2P视频技术源码(含开发文档) 目前的协议有如下一些特点: 1) 客户向服务器发送请求,...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...
p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...
p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...
p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...
p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端服务器端。 redui_src_v0.9.130(DirectUI 3D) DirectUI 3D界面库...
Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...
Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...