正文

P2P的简单示例(VB.net版)2008-05-03 17:11:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/iamben250/34805.html

分享到:

P2P的简单示例(VB.net版) 作者:不详    点击数:475    文章来源:不详    更新时间:2007-9-3      这是用VB.net实现的一个简单的P2P示例。利用了UDP打洞技术,分服务器端跟客户端,服务器端负责登陆记录用户的IP和端口及转发打洞消息。原理到处都有,这里就没有贴出来。这里贴出了VB.net的代码,供初学者交流,也欢迎高手点评……   服务器端在启动成功后,输入help可以查看到服务器相关命令。   客户端在登陆成功后,输入help可以查看客户端相关命令(登陆时用户名随便)。 以下是服务器端: Imports System.NetImports System.Net.SocketsImports System.TextImports System.ThreadingImports System.CollectionsModule myUDPServer#Region "全局变量"Dim ServerSocket As New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)Dim ipep As IPEndPoint = New IPEndPoint(IPAddress.Any, 11000)Dim htUserList As New Hashtable '用来保存在线用户和用户的"IP和端口"Dim userName(0) As StringDim userIPEP(0) As IPEndPointDim userTime(0) As IntegerDim timerDelegate As New TimerCallback(AddressOf onLineTimeOut)#End Region#Region "参数"'以下是客户端到服务器端的消息开头Const LOGININ As String = "10" '请求登陆的消息|||消息形式:10+自己的用户名Const LOGINOUT As String = "11" '请求登出的消息|||消息形式:11+自己的用户名Const GETULIST As String = "12" '请求获得在线用户列表|||消息形式:12Const P2PCONN As String = "13" '请求P2P连接的消息|||消息形式:13+自己的用户名+|+对方的用户名Const HOLDLINE As String = "14" '保持连接.|||消息开式:14+自己的用户名'以下是服务器到客户端的消息开头Const HVUSER As String = "20" '用户名已存在Const GETUSER As String = "21" '在线用户列表|||消息格式:21+用户名+EPConst MAKHOLD As String = "22" '打洞命令|||消息格式:22+IPConst LOGINOK As String = "23" '登陆成功Const SERVCLS As String = "24" '服务器关闭Const MSGEND As String = "25" '消息结束'以下是服务器端的命名Const EXITPRO As String = "EXIT" '退出命令Const SHOWULIST As String = "SHOWUSER" '显示在线用户Const HELP As String = "HELP" '显示帮助#End Region#Region "方法"'主函数,程序入口Sub Main()'获得服务器的IP地址Dim addressList As System.Net.IPAddress() = Dns.GetHostByName(Dns.GetHostName()).AddressListDim ServerIP As IPAddress = addressList(0)ServerSocket.Bind(ipep)Console.WriteLine("服务器正在启动....")Console.WriteLine("服务器IP:" & ServerIP.ToString & " 正在监听" & ipep.Port.ToString & "端口")Dim listenTH As New Thread(AddressOf listen)listenTH.Start() '启用监听的线程Console.WriteLine("服务器启动成功.....")Dim timer As New Timer(timerDelegate, Nothing, 0, 5000)Dim SVInput As StringWhile TrueConsole.Write("Server>")SVInput = Console.ReadLine().ToUpperSelect Case SVInputCase EXITPROlistenTH.Abort()ServerSocket.Close()Exit SubCase SHOWULISTshowUser()Case HELPConsole.Write("*********************************" & Chr(10) & Chr(13) & "exit:输出当前程序" & Chr(10) & Chr(13) & "showuser:显示当前在线用户例表" & Chr(10) & Chr(13) & "help:显示帮助" & Chr(10) & Chr(13) & "*********************************" & Chr(10) & Chr(13))Case ElseConsole.WriteLine("*********************************" & Chr(10) & Chr(13) & "笨瓜,你输入的不是有效的命令." & Chr(10) & Chr(13) & "*********************************")End SelectEnd WhileEnd Sub'打印在线用户Sub showUser()Dim hava As Boolean = FalseIf userName.Length <> 0 ThenDim i As IntegerFor i = 1 To userName.Length - 1If userName(i) <> "" Thenhava = TrueExit ForEnd IfNextIf hava = False ThenConsole.WriteLine("*********************************" & Chr(10) & Chr(13) & "当前没有用户在线" & Chr(10) & Chr(13) & "*********************************")Exit SubEnd IfConsole.WriteLine("*********************************")For i = 1 To userName.Length - 1If userName(i) <> "" ThenConsole.WriteLine("用户名:" & userName(i) & " 地址:" & userIPEP(i).ToString)End IfNextConsole.WriteLine("*********************************")ElseConsole.WriteLine("*********************************" & Chr(10) & Chr(13) & "当前没有用户在线" & Chr(10) & Chr(13) & "*********************************")End IfEnd Sub'服务器监听函数Sub listen()While TrueTryDim recv As Integer = 0Dim data As [Byte]() = New Byte(1024) {}Dim sender As New IPEndPoint(IPAddress.Any, 0)Dim tempRemoteEP As EndPoint = CType(sender, EndPoint)recv = ServerSocket.ReceiveFrom(data, tempRemoteEP)'Console.WriteLine(Encoding.Unicode.GetString(data))Dim msgHead As String = Encoding.Unicode.GetString(data, 0, 4)Select Case msgHeadCase LOGININDim LoginThing As String = userLogin(data, tempRemoteEP, recv)If LoginThing = HVUSER ThensendMsg(HVUSER, tempRemoteEP)ElseIf LoginThing = LOGINOK ThensendMsg(LOGINOK, tempRemoteEP)End IfCase LOGINOUTuserloginout(data, recv)Case GETULISTDim userinfo As String = getUserList()sendMsg(userinfo, tempRemoteEP)Case P2PCONNquestP2PConn(data, recv)Case HOLDLINEholdOnLine(data, recv)End SelectCatch e As Exception'Console.WriteLine(e.ToString)End TryEnd WhileEnd Sub'转发P2P连接请求Private Sub questP2PConn(ByVal data() As Byte, ByVal recv As Integer)Dim recvStr As String = Encoding.Unicode.GetString(data, 4, recv - 4)Dim split() As String = recvStr.Split("|")Dim fromEP As IPEndPointDim toEP As IPEndPointDim i As IntegerFor i = 1 To userName.Length - 1If userName(i) = split(0) ThenfromEP = userIPEP(i)End IfIf userName(i) = split(1) ThentoEP = userIPEP(i)End IfNextDim holdbytes() As Byte = Encoding.Unicode.GetBytes(MAKHOLD & fromEP.ToString)ServerSocket.SendTo(holdbytes, toEP)End Sub'函数.返回所有在线用户.其格式:用户名+|+用户IPEP+|Private Function getUserList() As StringDim userInfo As String = GETUSERDim i As IntegerFor i = 1 To userName.Length - 1If userName(i) <> "" ThenuserInfo += userName(i) & "|" & userIPEP(i).ToString & "|"End IfNextReturn userInfoEnd Function'用户登陆,直接返回登陆是否成功的值Private Function userLogin(ByVal data As Byte(), ByVal userEP As IPEndPoint, ByVal recvCount As Integer) As StringDim Uname As String = Encoding.Unicode.GetString(data, 4, recvCount - 4)Dim Uinfobytes() As ByteDim i As IntegerDim j As IntegerFor i = 1 To userName.Length - 1If Uname = userName(i) ThenReturn HVUSEREnd IfNextFor i = 1 To userName.Length - 1If userName(i) = "" ThenuserName(i) = UnameuserIPEP(i) = userEPuserTime(i) = 60Console.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)For j = 1 To userName.Length - 1If userName(j) <> "" And userName(j) <> Uname ThenServerSocket.SendTo(Uinfobytes, userIPEP(j))End IfNextReturn LOGINOKEnd IfNextDim userCount As Integer = userName.LengthReDim Preserve userName(userCount)ReDim Preserve userIPEP(userCount)ReDim Preserve userTime(userCount)userName(userName.Length - 1) = UnameuserIPEP(userIPEP.Length - 1) = userEPuserTime(userTime.Length - 1) = 60Console.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)For j = 1 To userName.Length - 1If userName(j) <> "" And userName(j) <> Uname ThenServerSocket.SendTo(Uinfobytes, userIPEP(j))End IfNextReturn LOGINOKEnd Function'用户登出Private Sub userloginout(ByVal data As Byte(), ByVal recvCount As Integer)Dim i As IntegerDim Uname As String = Encoding.Unicode.GetString(data, 4, recvCount - 4)For i = 1 To userName.Length - 1If Uname = userName(i) ThenDim loginOutMsg As String = LOGINOUT & userName(i)userName(i) = ""userIPEP(i) = NothinguserTime(i) = 0Dim j As IntegerFor j = 1 To userName.Length - 1If userName(j) <> "" ThensendMsg(loginOutMsg, userIPEP(j))End IfNextConsole.WriteLine(Chr(10) & Chr(13) & "*********************************")Console.WriteLine("用户" & Uname & "下线了.")Console.WriteLine("*********************************")Console.Write("Server>")Exit ForEnd IfNextEnd Sub'保持用户在线的过程Private Sub holdOnLine(ByVal data As Byte(), ByVal recvCount As Integer)Dim Uname As String = Encoding.Unicode.GetString(data, 4, recvCount - 4)Dim i As IntegerFor i = 1 To userName.Length - 1If Uname = userName(i) ThenuserTime(i) = 60Exit ForEnd IfNextEnd Sub'用户超时退出Private Sub onLineTimeOut(ByVal state As [Object])Dim i As IntegerFor i = 1 To userName.Length - 1If userTime(i) > 0 ThenuserTime(i) -= 5If userTime(i) <= 0 ThenDim loginoutmsg As String = LOGINOUT & userName(i)Console.WriteLine(Chr(10) & Chr(13) & "*********************************")Console.WriteLine("用户" & userName(i) & "下线了.")Console.WriteLine("*********************************")Console.Write("Server>")userName(i) = ""userIPEP(i) = NothingDim ULoginOutbytes() As Byte = Encoding.Unicode.GetBytes(loginoutmsg)Dim j As IntegerFor j = 1 To userName.Length - 1If userName(j) <> "" ThenIf userIPEP(j) Is Nothing ThenElseServerSocket.SendTo(ULoginOutbytes, userIPEP(j))End IfEnd IfNextEnd IfEnd IfNextEnd Sub'发送消息的函数Sub sendMsg(ByVal msg As String, ByVal remoteEP As IPEndPoint)Dim sendBytes As [Byte]() = Encoding.Unicode.GetBytes(msg)TryServerSocket.SendTo(sendBytes, remoteEP)Catch e As ExceptionConsole.WriteLine(e.ToString())End TryEnd Sub#End RegionEnd Module 以下是客户端: Imports System.NetImports System.Net.SocketsImports System.TextImports System.ThreadingModule Module1#Region "参数"'以下是客户端到服务器端的消息开头Const LOGININ As String = "10" '请求登陆的消息|||消息形式:10+自己的用户名Const LOGINOUT As String = "11" '请求登出的消息|||消息形式:11+自己的用户名Const GETULIST As String = "12" '请求获得在线用户列表|||消息形式:12+自己的用户名Const P2PCONN As String = "13" '请求P2P连接的消息|||消息形式:13+自己的用户名+对方的用户名Const HOLDLINE As String = "14" '保持连接.|||消息开式:14+自己的用户名'以下是服务器到客户端的消息开头Const HVUSER As String = "20" '用户名已存在Const GETUSER As String = "21" '在线用户列表|||消息格式:21+用户名+EPConst MAKHOLD As String = "22" '打洞命令|||消息格式:22+IPConst LOGINOK As String = "23" '登陆成功Const SERVCLS As String = "24" '服务器关闭Const MSGEND As String = "25" '消息结束   的简单示例(VB.net版) 作者:不详    点击数:476    文章来源:不详    更新时间:2007-9-3    '以下是客户端到客户端的消息开头Const HOLDOK As String = "30" '打洞成功Const CHATMSG As String = "31" '聊天消息Const CHTMSGEND As String = "32" '聊天消息发送成功'以下是客户端的命名Const EXITPRO As String = "EXIT" '退出命令Const SHOWULIST As String = "SHOWUSER" '显示在线用户Const HELP As String = "HELP" '显示帮助Const SEND As String = "SEND" '发送消息#End Region#Region "全局全量"Delegate Sub myMethodDelegate(ByRef myInData As Byte()) '登陆时用的事件'Dim MaxTry As Integer = 5Dim msgSendEnd As Boolean = False '消息是否发送成功,若发送成功,则会返回结束消息Dim ThListen As New Thread(AddressOf listen) '监听的线程Dim ClientSocket As New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) '客户端套节字的定义Dim username As String '当前用户名Dim ServerEP As IPEndPoint '服务器的IPEPDim holdBytes As [Byte]() = Encoding.Unicode.GetBytes(HOLDLINE & username) '和服务器保持连接连接时用到的byte数组Dim OLUserName() As StringDim OLUserEP() As IPEndPointDim getUrecCount As IntegerDim testHold As Boolean = FalseDim testChat As Boolean = FalsePrivate receiveDone As ManualResetEvent '在登陆时用来阻塞线程,等待收到数据Private sendDone As ManualResetEvent '用来阴塞发送消息的线程.等待收到回送的确认消息Private getUDone As ManualResetEvent '用来阻塞请求好友名单的线程,等待接收好友名单Private holdDone As ManualResetEvent '用来阻塞打洞时的线程Private chatDone As ManualResetEvent '用来阻塞发送聊天消息时的线程Dim timerDelegate As New TimerCallback(AddressOf holdonline) '为保持在线状态弄得#End Region#Region "方法"'主函数,程序入口Sub Main()Dim InputIP As StringDim InputOK As Boolean = False'判断输入的IP,并且保存服务器的IPEPWhile InputOK <> TrueConsole.Write("请输入服务器IP:")InputIP = Console.ReadLine()TryServerEP = New IPEndPoint(IPAddress.Parse(InputIP), 11000)InputOK = TrueCatchConsole.WriteLine("你输入的服务器IP不正确,请重新输入.")InputOK = FalseEnd TryEnd WhileDim bool As Boolean = False'判断用户是否登陆成功While bool <> TrueDim LoginOK As Boolean = Login()If LoginOK = True Thenbool = TrueElseConsole.Write("是否重试:输入Y重试,输入任意值退出程序:")Dim tempYN As String = Console.ReadLine.ToUpperIf tempYN = "Y" Thenbool = FalseElseExit SubEnd IfEnd IfEnd WhileConsole.WriteLine("用户名:" & username)holdBytes = Encoding.Unicode.GetBytes(HOLDLINE & username)'登陆成功后.用一个timer,每隔50秒向服务器发送消息,保持在线状态跟在主机注册的端口Dim timer As New Timer(timerDelegate, Nothing, 10000, 50000)'请求在线名单Console.WriteLine("正在获取在线名单,请稍后....")Dim getUbool As Boolean = FalseWhile getUbool <> TruegetUbool = getU()If getUbool = False ThenConsole.Write("是否重试:输入Y重试,输入任意值退出程序:")Dim tempYN As String = Console.ReadLine.ToUpperIf tempYN = "Y" Thenbool = FalseElseExit SubEnd IfEnd IfEnd WhileThListen.Start()'用来处理客户端的一些命令Dim SVInput As StringWhile TrueConsole.Write("Client>")SVInput = Console.ReadLine().ToUpperSelect Case SVInputCase EXITPROexitApp()ThListen.Abort()ClientSocket.Close()Exit SubCase SHOWULISTConsole.WriteLine("*********************************")showUserList()Console.WriteLine("*********************************")Case HELPConsole.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))Case ElseIf SVInput.Substring(0, 4) = "SEND" ThenDim split() As String = SVInput.Split(" ")If split.Length = 3 ThensendChatMsg(split(1), split(2))ElseConsole.WriteLine("*********************************" & Chr(10) & Chr(13) & "你输入的命令格式不正确.send命令格式为:send 用户名 你的消息" & Chr(10) & Chr(13) & "*********************************")End IfElseConsole.WriteLine("*********************************" & Chr(10) & Chr(13) & "笨瓜,你输入的不是有效的命令." & Chr(10) & Chr(13) & "*********************************")End IfEnd SelectEnd WhileEnd Sub'登陆函数Private Function Login() As BooleanreceiveDone = New ManualResetEvent(False)Dim userBytes As [Byte]()Dim userOK As Boolean = FalseConsole.Write("请输入你的用户名:")'判断用户名是否符合格式While (userOK <> True)username = Console.ReadLine.ToUpperuserBytes = Encoding.Unicode.GetBytes(LOGININ & username)If userBytes.Length > 24 Or userBytes.Length < 10 ThenConsole.WriteLine("用户名不得小于6个字节,且不得大于20个字节.")Console.Write("请重新输入你的用户名:")ElseuserOK = TrueEnd IfEnd While'向服务器发送客户消息ClientSocket.SendTo(userBytes, ServerEP)Dim data As [Byte]() = New Byte(1024) {}Dim comStr As String = Encoding.Unicode.GetString(data, 0, 4)'异面的接收服务器回送的消息Dim DGrecv As New myMethodDelegate(AddressOf recvLogin)DGrecv.BeginInvoke(data, Nothing, Nothing)'等待服务器回送消息的时长为10秒,否则为服务器超时receiveDone.WaitOne(30000, True)Dim recvStr As String = Encoding.Unicode.GetString(data, 0, 4)If recvStr = comStr ThenConsole.WriteLine("服务器超时.登陆失败!!")Return FalseEnd IfIf Encoding.Unicode.GetString(data, 0, 4) = LOGINOK ThenConsole.WriteLine("登陆成功!!")Return TrueElseIf Encoding.Unicode.GetString(data, 0, 4) = HVUSER ThenConsole.WriteLine("用户名重复.登陆失败!!")Return FalseElseConsole.WriteLine("服务器未知错误,登陆失败!!")Return FalseEnd IfEnd Function'登出函数Private Sub exitApp()Dim loginOutStr As String = LOGINOUT & usernameDim sendBytes As [Byte]() = Encoding.Unicode.GetBytes(loginOutStr)ClientSocket.SendTo(sendBytes, ServerEP)End Sub'请求好友列表的函数Private Function getU() As BooleangetUDone = New ManualResetEvent(False)Dim getUbytes As Byte() = Encoding.Unicode.GetBytes(GETULIST)ClientSocket.SendTo(getUbytes, ServerEP)Dim data As [Byte]() = New Byte(4056) {}Dim comStr As String = Encoding.Unicode.GetString(data, 0, 4)Dim GUrecv As New myMethodDelegate(AddressOf recvGetU)GUrecv.BeginInvoke(data, Nothing, Nothing)getUDone.WaitOne(30000, True)Dim recvStr As String = Encoding.Unicode.GetString(data, 0, 4)If recvStr = comStr ThenConsole.WriteLine("服务器超时.或取好友名单失败!!")Return FalseEnd IfIf Encoding.Unicode.GetString(data, 0, 4) = GETUSER ThengetUserList(data, getUrecCount)Console.WriteLine("获取在线名单成功!!")showUserList()Return TrueElseConsole.WriteLine("服务器未知错误,获取在线名单失败!!")Return FalseEnd IfEnd Function'登陆时用来异步的接收服务器发送的消息Sub recvLogin(ByRef inData As Byte())ClientSocket.Receive(inData)receiveDone.Set()End Sub'请求好友名单时用来异步接收服务器发送的消息Sub recvGetU(ByRef inData As Byte())getUrecCount = ClientSocket.Receive(inData)getUDone.Set()End Sub'处理收到的在线用户信息Private Sub getUserList(ByVal userInfobytes() As Byte, ByVal reccount As Integer)Dim ustr As String = Encoding.Unicode.GetString(userInfobytes, 4, reccount - 4)Dim splitStr() As String = NothingsplitStr = Ustr.Split("|")Dim IPEPSplit() As String = NothingDim i As Integer = 0Dim k As IntegerFor k = 0 To splitStr.Length - 2 Step 2ReDim Preserve OLUserName(i)ReDim Preserve OLUserEP(i)OLUserName(i) = splitStr(k)IPEPSplit = splitStr(k + 1).Split(":")OLUserEP(i) = New IPEndPoint(IPAddress.Parse(IPEPSplit(0)), IPEPSplit(1))IPEPSplit = Nothingi += 1NextEnd Sub'显示在线用户Private Sub showUserList()Dim i As IntegerFor i = 0 To OLUserName.Length - 1If OLUserName(i) <> "" ThenConsole.WriteLine("用户名:" & OLUserName(i) & " 用户IP:" & OLUserEP(i).ToString)End IfNextEnd Sub'客户程序监听的函数Sub listen()While TrueTryDim recv As Integer = 0 '收到的字节数Dim data As [Byte]() = New Byte(1024) {} '缓冲区大小Dim sender As New IPEndPoint(IPAddress.Any, 0)Dim tempRemoteEP As EndPoint = CType(sender, EndPoint)recv = ClientSocket.ReceiveFrom(data, tempRemoteEP)Dim msgHead As String = Encoding.Unicode.GetString(data, 0, 4) '获得消息头的内容Select Case msgHeadCase MSGENDmsgSendEnd = TruesendDone.Set()Case LOGININaddOnLine(data, recv)Case LOGINOUTremoveOnLine(data, recv)Case MSGENDmsgSendEnd = TruesendDone.Set()Case MAKHOLDConsole.WriteLine(Chr(10) & Chr(13) & "收到打洞消息.")makeHold(data, recv)Console.Write("Client>")Case CHATMSGshowChatMsg(data, recv)Case HOLDOKtestHold = TrueholdDone.Set()Case CHTMSGENDtestChat = TruechatDone.Set()End SelectCatchEnd TryEnd WhileEnd Sub'发送聊天消息Private Sub sendChatMsg(ByVal remoteUser As String, ByVal chatMsgStr As String)If remoteUser = username ThenConsole.WriteLine("猪头,你想干什么!!!")Exit SubEnd IfDim i As IntegerDim remoteUEP As IPEndPointFor i = 0 To OLUserName.Length - 1If remoteUser = OLUserName(i) ThenremoteUEP = OLUserEP(i)Exit ForEnd IfIf i = OLUserName.Length - 1 ThenConsole.WriteLine("找不到你想发送的用户.")Exit SubEnd IfNextDim msgbytes() As Byte = Encoding.Unicode.GetBytes(CHATMSG & username & "|" & chatMsgStr)Dim holdbytes() As Byte = Encoding.Unicode.GetBytes(P2PCONN & username & "|" & remoteUser)chatDone = New ManualResetEvent(False)ClientSocket.SendTo(msgbytes, remoteUEP)chatDone.WaitOne(10000, True)If testChat = True ThentestChat = FalseExit SubEnd IftestHold = FalseWhile testHold <> TrueConsole.WriteLine("打洞ing.....")holdDone = New ManualResetEvent(False)ClientSocket.SendTo(holdbytes, remoteUEP)ClientSocket.SendTo(holdbytes, ServerEP)holdDone.WaitOne(10000, True)If testHold = True ThenExit WhileElseConsole.WriteLine("打洞超时,发送消息失败.")Console.Write("是否重试,按Y重试,按任意值结束发送:")Dim YorN As String = Console.ReadLine().ToUpperIf YorN = "Y" ThentestHold = FalseElseExit SubEnd IfEnd IfEnd WhileWhile testChat <> TrueConsole.WriteLine("打洞成功,正在准备发送.....")chatDone = New ManualResetEvent(False)ClientSocket.SendTo(msgbytes, remoteUEP)chatDone.WaitOne(10000, True)If testChat = True ThenConsole.WriteLine("消息发送成功!!")Exit WhileElseConsole.WriteLine("发送超时,发送消息失败.")Console.Write("是否重试,按Y重试,按任意值结束发送:")Dim YorN As String = Console.ReadLine().ToUpperIf YorN = "Y" ThentestChat = FalseElseExit SubEnd IfEnd IfEnd WhiletestHold = FalsetestChat = FalseEnd Sub'处理聊天消息Private Sub showChatMsg(ByVal indata() As Byte, ByVal recvcount As Integer)Dim msgStr As String = Encoding.Unicode.GetString(indata, 4, recvcount - 4)Dim splitStr() As String = msgStr.Split("|")Dim fromUname As String = splitStr(0)Dim msg As String = splitStr(1)Console.WriteLine(Chr(10) & Chr(13) & "收到来自" & fromUname & "的消息:" & msg)Console.Write("Client>")Dim i As IntegerFor i = 0 To OLUserName.Length - 1If OLUserName(i) = fromUname ThenExit ForEnd IfNextDim tempbytes() As Byte = Encoding.Unicode.GetBytes(CHTMSGEND)ClientSocket.SendTo(tempbytes, OLUserEP(i))End Sub'处理打洞函数Private Sub makeHold(ByVal indata() As Byte, ByVal recvcount As Integer)Dim makholdstr As String = Encoding.Unicode.GetString(indata, 4, recvcount)Dim ipepstr() As String = makholdstr.Split(":")Dim holdEP As IPEndPoint = New IPEndPoint(IPAddress.Parse(ipepstr(0)), ipepstr(1))Dim holdbytes() As Byte = Encoding.Unicode.GetBytes(HOLDOK & username)ClientSocket.SendTo(holdbytes, holdEP)Console.WriteLine("回送打洞消息.")End Sub'处理用户上线的函数Private Sub addOnLine(ByVal inData() As Byte, ByVal recvCount As Integer)Dim inStr As String = Encoding.Unicode.GetString(inData, 4, recvCount - 4)Dim userinfo() As String = inStr.Split("|")Dim strUserEP() As String = userinfo(1).Split(":")Dim i As IntegerFor i = 0 To OLUserName.Length - 1If OLUserName(i) = "" ThenOLUserName(i) = userinfo(0)OLUserEP(i) = New IPEndPoint(IPAddress.Parse(strUserEP(0)), strUserEP(1))Console.WriteLine(Chr(10) & Chr(13) & "用户" & OLUserName(i) & "上线了. 用户地址:" & OLUserEP(i).ToString)Console.Write("Client>")Exit SubEnd IfNextReDim Preserve OLUserName(i + 1)ReDim Preserve OLUserEP(i + 1)OLUserName(i + 1) = userinfo(0)OLUserEP(i + 1) = New IPEndPoint(IPAddress.Parse(strUserEP(0)), strUserEP(1))Console.WriteLine(Chr(10) & Chr(13) & "用户" & OLUserName(i + 1) & "上线了. 用户地址:" & OLUserEP(i + 1).ToString)Console.Write("Client>")End Sub'处理用户下线的函数Private Sub removeOnLine(ByVal inData() As Byte, ByVal recvCount As Integer)Dim offUname As String = Encoding.Unicode.GetString(inData, 4, recvCount - 4)Dim i As IntegerFor i = 0 To OLUserName.Length - 1If OLUserName(i) = offUname ThenOLUserName(i) = ""OLUserEP(i) = NothingConsole.WriteLine(Chr(10) & Chr(13) & "用户" & offUname & "下线了.")Console.Write("Client>")Exit SubEnd IfNextEnd Sub'发送消息的函数Public Function sendmsg(ByVal msg As String, ByVal sendToIPEP As IPEndPoint) As StringDim sendBytes As [Byte]() = Encoding.Unicode.GetBytes(msg)'判断发送的字节数是否超过了服务器缓冲区大小If sendBytes.Length > 1024 ThenReturn "W输入的字数太多"End If'判断消息是否发送成功While msgSendEnd = FalsesendDone = New ManualResetEvent(False)TryClientSocket.SendTo(sendBytes, sendToIPEP)sendDone.WaitOne(10000, True) '阻塞线程10秒If msgSendEnd = False ThenConsole.WriteLine("消息发送超时")ElseExit WhileEnd IfCatch e As ExceptionConsole.WriteLine("发送消息失败" & e.ToString)Exit FunctionEnd TryConsole.Write("是否重试?按Y重试,按任意键退出:")Dim userInput As String = Console.ReadLine.ToUpperIf userInput = "Y" ThenElsemsgSendEnd = FalseExit FunctionEnd IfEnd WhilemsgSendEnd = FalseEnd Function'用保持在线状态的函数Private Sub holdonline(ByVal state As [Object])ClientSocket.SendTo(holdBytes, ServerEP)End Sub#End RegionEnd Module

阅读(1365) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册