出处:http://www.webp2p.com/downloads/ASimpleIM.htm
主站:http://www.webp2p.com/
本章中将以一个简单的VB例子来引导你快速进入PRTX的世界。如果使用其它语言,调用方式是一样的。
这个简单的即时通讯,有用户注册,用户登录和好友列表显示功能,然后能发文字信息给其中一个选中的好友。
开发前,首先需要将即时通讯的客户端DllShareRes.dll放到windows的system 32 目录下,以便vb程序能调用到DllShareRes.dll,,设置ODBC驱动,将系统DSN命名为ShareRes2,并和数据库shareResV2.mdb建立连接,使服务器能够操作数据库, 并运行p2p服务器(ShareResServer.exe),企业版本可以使用SqlServer库,以应对企业级大用户量情况。
总之,您需要以下模块
P2P通讯模块:DllShareRes.dll 学习版
P2P服务器模块:ShareResServer.exe 学习版
数据库:ShareResV2.mdb
需要源代码请联系君曼公司
www.webp2p.com
数据库 |
P2p服务器 |
Internet |
客户端 |
远程数据库连接 |
DllShareRes.dl 登陆p2p服务器 |
客户端 |
客户端 |
在本例子中与数据库的交换将通过数据库远程访问对象来做,比如通过ADO连接远程数据库的IP连接到数据库。权限控制等都通过远程数据库控制。
登录通过P2P模块来通讯,P2P服务器将自动验证用户名和密码,下发是否成功信息,同时会下发好友列表,以及好友的IP地址信息。
发送信息将通过P2P通讯模块来发送。
P2P通讯模块还将自动下发好友的上线下线通知,以及跟踪好友IP地址的变化,下发好友IP地址。
shareResV2.mdb是本示例的数据库,将用到其中三个表,分别是UserBrief ,这个表用来存储常用用户信息,以加快访问速度,friends表用来存储用户好友列表信息,msgboard 保存留言信息。下面予以分别说明。
UserBrief表主要字段说明
字段名称 |
数据类型 |
说明 |
UIN |
数字 |
用户登陆号,是用户的标志,和QQ号一样的 |
Password |
文本 |
|
UserName |
文本 |
用户名,支持用户名和号码同时登录。 |
BAuth |
是/否 |
是否需要验证才能加这个人为好友 |
City |
文本 |
|
Province |
文本 |
|
bIsParentOrganization |
是/否 |
父亲是否是组织,如果是组织,就到Organization表里找信息,否则就在个人表里找信息 |
NParent |
数字 |
父亲是谁,可以是组织或者是个人 |
NPoints |
数字 |
积分 |
NType |
数字 |
用户类别,角色,如学生,家长,老师 |
AuthGroup |
数字 |
所在权限组别,和nType不同. 权限分级1,2,3等 |
IconID |
数字 |
头像ID,与客户机上的Icon文件名对应 |
Sex |
是/否 |
|
Nick |
文本 |
|
BOnline |
数字 |
状态 |
Age |
数字 |
年龄 |
Country |
文本 |
国家 |
sMobile |
文本 |
|
|
文本 |
|
sign |
文本 |
签名 |
onlineTime |
数字 |
在线时长总计,以分钟为单位 |
nLoginTimes |
数字 |
登录次数 |
nLastLoginTime |
数字 |
上次登录时间 |
nRegisterTime |
数字 |
注册时间 |
用户注册时,数据存入friends 表,uin号是系统自动分配的号码和QQ号一样的,当用户登陆时系统从这个表里提取用户信息.
Msgboard表,这个表存储用户留言信息
字段名称 |
数据类型 |
说明 |
ID |
自动编号 |
主键 |
AccountTo |
数字 |
接收者uin号 |
Msg |
文本 |
|
AccountFrom |
数字 |
发送者uin号 |
theTime |
文本 |
|
type |
数字 |
|
Friends表,这个表保存用户好友例表
字段名称 |
数据类型 |
说明 |
ID |
自动编号 |
|
UIN |
数字 |
|
ContactGroupID |
数字 |
组ID,比如我的好友 =1 , 陌生人 = 2, 现在没有用 |
GroupName |
文本 |
|
Friends |
备注 |
纪录好友uin好,可能是多个以逗号隔开 |
Num |
数字 |
好友个数,无用 |
nParentID |
数字 |
父亲组号 |
用户注册模块,在VB可以使用常用的数据库远程访问对象来做,比如通过ADO连接远程数据库的IP连接到数据库。
用户注册,也可以通过网页的方式来注册,这种用户注册太多了,不需要详细说明。
用户登录需要通过即时通讯的DllShareRes.dll来登录P2P服务器,这样,P2P服务器才会保存好用户信息,并在他的好友上线时交换IP地址等。
需要用到的函数说明
l StartUp(long addrLeaveMsg, long addrLanStatus, long addlocalErr, long addrTimer, long addrGetMsg, long addrOnline, long addrSysMsg, long addrAdvSearch)
说明:初始化回调函数地址。传入界面
调用DllShareRes.dll之前,需要初始化Dll,初始化Dll由StartUp函数完成。这个函数的参数都是Dll可能用到的回调函数地址。
回调函数,就是Dll在收到服务器的反馈时,所被调用的VB函数,在DllShareRes.dll中,所有VB回调函数都以exe开头,表明这个函数由Dll来调用的。比如ExeLoginReply,这个函数是用户登录成功后Dll要调用的函数。用户可以在所有的回调函数里添加代码。
l Sub ExeLoginReply(ByVal UIN As Long, ByVal i As Long, ByVal parm As String)
如果登陆成功系统将自动返回这个函数 这个函数的参数parm包含有登录用户的详细信息,及登录成功后自己的QQ号码。
‘UIN 用户的QQ号
‘I 无用
‘Parm 是如下字符串格式: ‘IconID=Nick=UserName=BAuthType=bSex=nAuthGroup=sIP=nPort=City=Province=country=nLanStatus=age=sMoblie=nStatus
l SetNetworkDll(LPCTSTR sIP, USHORT nPort, LPCTSTR sProxyIP, USHORT nProxyPort, LPCTSTR sUserName, LPCTSTR sPass)
说明:设置网络,包括代理服务器
sIP à服务器IP
nPort à服务器端口
sProxyIP à设置代理上网IP
nProxyPort à设置代理端口
sUserName à设置代理用户名
sPass à设置代理密码
一般,SetNetworkDll不需要设置代理,仅设置服务器和端口就行了。
l Sub ExeSysMsg(ByVal e As Integer, ByVal i As Long, ByVal parm As String)
'返回系统消息或者错误码,e是codes, i是哪个命令的返回消息,i可能不用,parm备用
例如如果用户登陆成功e=E_LOGIN_SUC 表示登陆成功,如果登陆不成功根据e的值可以判断登陆不成功的原因
l Public Declare Sub CmdReqContactListDll Lib "DllShareRes.dll" (ByVal addr As Long)
说明:表示需要服务器下传好友列表。
可以在ExeLoginReply函数中调用CmdReqContactListDll函数,以便在登陆成功时自动调用用户好友列表,
Addr是收到好友列表的回调函数地址。一般是回调函数ExeReqContactList地址,这样在ExeReqContactList函数的参数parm中返回用户全部好友列表。
l Sub ExeReqContactList(ByVal UIN As Long, ByVal i As Long, ByVal parm As String)
说明获得的好友列表, parm为好友及组信息,parm为:组号=组名=Nick Name=是否需要验证=图标ID=UIN=在线状态,用户可以在这个函数中添加好友列表显示代码。
const BATCH_VIS_LIST = 2
const BATCH_SEARCH_LIST = 3
l Sub ExeAdvSearch(ByVal UIN As Long, ByVal i As Long, ByVal parm As String)
这个函数表示收到一批用户,有两种类型,I = BATCH_VIS_LIST 表示是上线好友,I= BATCH_SEARCH_LIST表示查找到的列表
用户登陆成功时自动返回该函数,当I = BATCH_VIS_LIST,parm 参数值是上线好友的信息parm是 UIN=Status=nIP=nPort=防火墙。
CmdLoginDll |
ExeLoginReply |
ExeSysMsg 表明错误原因 |
成功 |
登录不成功 |
CmdReqContactListDll 需要好友列表 |
例子, 10000号用户登录。
ExeReqContactList 获得好友列表 |
ExeSysMsg 收到消息码 E_CONTACT_LIST_END 表示好友例表已经全部传完 |
ExeAdvSearch 获得上线的好友IP地址 |
Private Sub Form_Load()
'启动Dll模块
Call StartUp(AddressOf ExeGetLeaveMsg, AddressOf ExeLanStatus, AddressOf ExeLocalErr, AddressOf ExeSetTimer, AddressOf ExeGetMsg, AddressOf ExeUserOnline, AddressOf ExeSysMsg, AddressOf ExeAdvSearch)
SetNetworkDll "218.16.122.102", 3288, "", 0, "", ""
Call CmdLoginDll(AddressOf ExeLoginReply, 2, 10000, "", "123321")
End Sub
上例登陆的服务器地址是"218.16.122.102",端口 3288 ,登陆号码是10000,密码是123321,用户可以根据需要进行设置
如果登录成功,则ExeLoginReply会被调用,在exeLoginReply中,登录成功后,VB程序可以做任何事情,比如可以通过ADO连接远程数据库,取下自己的用户信息
Sub ExeLoginReply(ByVal UIN As Long, ByVal i As Long, ByVal parm As String)
‘UIN 是登录成功后自己的QQ号码。
‘这里远程连接数据库,从自己的用户表里取下自己的信息。
'需要服务器下传好友列表
Call CmdReqContactListDll(AddressOf ExeReqContactList)
end sub
如果登录不成功,返回系统错误码
Sub ExeSysMsg(ByVal e As Integer, ByVal i As Long, ByVal parm As String)
lmsg "ExeSysMsg:::::::::::::::" & e & "i=" & "parm=" & parm & "登录状态 " & g_stMe.nStatus
Select Case e
Case E_SUCCEED
'MsgBox "操作成功" ' //操作成功,不需要提示
Case E_NO_UIN
frmMain.UserState.Caption = "登录的用户ID不存在" '12010 //登录不成功,用户名不存在
Case E_LOGIN_FAIL
frmMain.UserState.Caption = "登录不成功,其它原因"
Case E_SOKET_CREATE
MsgBox "无法创建socket", vbCritical, g_sAppName
Case Else
' MsgBox "服务器返回: " & e & " " & parm, vbInformation, g_sAppName
End Select
End Sub
'得到好友列表,并加好友信息加到窗口中显示
Sub ExeReqContactList(ByVal UIN As Long, ByVal i As Long, ByVal parm As String)
Debug.Print "ExeReqContactList::::::::::::: UIN: " & UIN & ", i:" & i & ", parm: " & parm
Dim GroupNameNo As Integer, UserFriend() As String
Dim FriendNum As Long, Group() As String, GroupNum As Long, ii As Long
Dim GroupName As String
Dim UserFriendOne() As String
Dim sNick As String
Dim sIcon As String
Dim sIP As String
Dim nPort As Long
Dim theUIN As Long
Dim USER_ITEMS As Integer
USER_ITEMS = 7 '一个用户数据包括的字段数
'拆分出ContactList内容
Group = Split(parm, "=")
GroupNum = UBound(Group)
GroupNameNo = Group(0) '组号
GroupName = Group(1) '组名
If GroupNum < USER_ITEMS Then
'如果只有组,无成员
Debug.Print "如果只有组,无成员: " & GroupName, GroupNameNo
Form1.TreeView1.Nodes.Add "root", tvwChild, UserB(1), UserB(1)
Else
Dim IconID As Integer
'如果为7
For ii = 0 To ((GroupNum - 2) / USER_ITEMS) - 1
theUIN = CLng(Group(2 + 3 + USER_ITEMS * ii))
sIcon = Group(2 + 2 + USER_ITEMS * ii)
sNick = Group(2 + 0 + USER_ITEMS * ii)
sIP = Group(2 + 5 + USER_ITEMS * ii)
If Len(Group(2 + 6 + USER_ITEMS * ii)) > 0 Then
nPort = CLng(Group(2 + 6 + USER_ITEMS * ii))
Else
nPort = 0
End If
lmsg "ExeReqContactList::ListAllUser1.AddMemberOne 组号: " & GroupNameNo & " 组名: " & GroupName & _
" 用户: " & theUIN & _
" Nick: " & sNick & _
" 是否需要验证: " & Group(2 + 1 + USER_ITEMS * ii) & _
" 图标ID : " & sIcon & _
" 在线状态: " & Group(2 + 4 + USER_ITEMS * ii) & _
" IP地址: " & sIP & _
" 端口: " & CStr(nPort)
' Dim IconID As Integer
IconID = CInt(sIcon)
If IconID > HEADER_IMAGE_COUNT Then
IconID = 0
End If
'LHJ 在线状态 用0 表示未定义,因为从服务器上取下来的只是数据库里上线的状态,给网页用的
'而软件是会收到上线好友消息的,因此不用在这里读状态
If UserB(2 + 0 + USER_ITEMS * ii) <> "" Then
Form1.TreeView1.Nodes.Add UserB(1), tvwChild, UserB(2 + 0 + USER_ITEMS * ii) + "'" + _UserB(5 + 0 + USER_ITEMS * ii) + "'", UserB(2 + 0 + USER_ITEMS * ii) + "'" + UserB(5 + 0 _+ USER_ITEMS * ii) + "'", UserB(4 + 0 + USER_ITEMS * ii) + 1
End If
Next
End If
End Sub
l CmdSendMsgDll(USHORT msgtype, USHORT nLanstatus, long addr, ULONG hisUIN, LPCTSTR sDestIP, USHORT DestPort, LPCSTR mes)
说明:发送消息给对方
其中msgType是消息类型,可以自定义,比如msgType为100,可表示这是发文件的请求信息。MsgType为120可表示为请求语音的信息等等。
sDestIP, DestPort 是对方的ip地址和端口,可以在用户登陆时从ExeAdvSearch函数得到上线好友的ip地址和端口
mes是发送消息的内容
CmdLeaveMsgDll(USHORT msgtype, long addr, ULONG hisUIN, LPCSTR mes)
说明:发送留言给对方。
使用:如果对方的IP地址是空的,也就是对方不在线,就可以在调用此函数留言到服务器上。
下面是一个用VB开发的实例:
登陆界面如下图
首先在vb中新建一个工程,并向工程中另外添加三个窗体,form1,form2,form3,form4,分别用来作为,主窗体,登陆界面,注册界面,发送消息界面, 界面外观如下图。另外还须向工程中添加一共用模块Module1,放置DllShareRes.dl的函数声明,和回调函数 。
下面予以分别说明。
(1). 主窗体form1 ,如下图一显示,点击登陆按钮,则进入登陆界面,登陆成功后 主窗体显示用户好友列表,背景为蓝色表示好友在线,双击用户名,进入发送消息界面,
主窗体的主要控件
控件 |
命名 |
说明 |
frame |
Frame1 |
运行时主窗体先显示,frame1,frame2,frame3,登陆成功后,frame1,frame2,frame3隐藏,frame4,frame5,显示 |
frame |
Frame2 |
|
frame |
Frame3 |
|
frame |
Frame4 |
|
frame |
Frame5 |
|
CommandButton |
Command1 |
登陆按钮 |
TreeView |
Treeview1 |
显示用户列表,在frame4上 |
Timer |
DllTime |
DllShareRes.dll里用到 |
Timer |
Timer1 |
|
label |
Label1 |
在frame1上, |
label |
Label2 |
在frame5上, |
image |
Image1 |
在frame5上,显示用户图像 |
图一 图二
图三 图四
窗体初始化代码如下:
Private Sub Form_Load()
TreeView1.ImageList = Form3.ImageList1
login1 = False '公用变量初始化
loginlist = False
g_sendMessage = False
g_clickevent = False
TreeView1.Nodes.Add , , "root", "好友列表"
'初始化回调函数
Call StartUp(AddressOf ExeGetLeaveMsg, AddressOf ExeLanStatus, AddressOf ExeLocalErr, AddressOf ExeSetTimer, AddressOf ExeGetMsg, AddressOf ExeUserOnline, AddressOf ExeSysMsg, AddressOf ExeAdvSearch)
CmdiniLog "MaimPro", False
Frame4.Visible = False
Frame5.Visible = False
Frame1.Visible = True
Frame2.Visible = True
Frame3.Visible = True
End Sub
登陆成功后返回好友列表代码如下
Sub ExeReqContactList(ByVal uin As Long, ByVal i As Long, ByVal parm As String)
lmsg " "
lmsg "ExeReqContactList::::::::::::: UIN: " & uin & ", i:" & i & ", parm: " & parm
Debug.Print "ExeReqContactList::::::::::::: UIN: " & uin & ", i:" & i & ", parm: " & parm
Dim UserB() As String
Dim iii As Integer
Dim iiii As Integer
Dim GroupNameNo As Integer, UserFriend() As String
Dim FriendNum As Long, Group() As String, GroupNum As Long, ii As Long
Dim GroupName As String
Dim UserFriendOne() As String
Dim sNick As String
Dim sIcon As String
Dim sIP As String
Dim nPort As Long
Dim theUIN As Long
Dim USER_ITEMS As Integer
USER_ITEMS = 7 '一个用户数据包括的字段数
UserB = Split(parm, "`")
GroupNum = UBound(UserB)
If GroupNum < USER_ITEMS Then
Debug.Print "如果只有组,无成员: " & UserB(0), UserB(1)
Form1.TreeView1.Nodes.Add "root", tvwChild, UserB(1), UserB(1)
Else
‘添加组名
Form1.TreeView1.Nodes.Add "root", tvwChild, UserB(1), UserB(1)
Dim IconID As Integer
‘向TREEVIEW1添加好友列表
For ii = 0 To ((GroupNum - 2) / USER_ITEMS) - 1
If UserB(2 + 0 + USER_ITEMS * ii) <> "" Then
Form1.TreeView1.Nodes.Add UserB(1), tvwChild, UserB(2 + 0 + USER_ITEMS * ii) + "'" + UserB(5 + 0 + USER_ITEMS * ii) + "'", UserB(2 + 0 + USER_ITEMS * ii) + "'" + UserB(5 + 0 + USER_ITEMS * ii) + "'", UserB(4 + 0 + USER_ITEMS * ii) + 1
End If
Next ii
Form1.TreeView1.Nodes(1).Expanded = True
End If
End Sub
当ExeReqContactList返回好友列表,存在树的节点中。ExeAdvSearch返回上线好友,存在onlineuser()数组中,并在树中搜索上线好友,在主界面的树状列表中把在线好友背景加为蓝色
显示在线好友代码如下,
Private Sub Timer1_Timer()
If login1 = True And loginlist = True Then ‘判断在线好友列表和好友列表是否已经返回
Dim iiii As Integer
Dim iii As Integer
Dim count As Integer
Dim str11 As String
Dim uin1() As String
Dim ite As Integer
ite = 0
count = Form1.TreeView1.Nodes.count
iiii = onlineUser(0).bl
' MsgBox "onlineUser.bl" & onlineUser(0).bl
For iii = 0 To iiii - 1
For ite = 2 To count
childcount = Form1.TreeView1.Nodes(ite).Children
If childcount = 0 And Form1.TreeView1.Nodes(ite).Parent <> Form1.TreeView1.Nodes(1) Then
str11 = Form1.TreeView1.Nodes(ite).Text
uin1 = Split(str11, "'")
Debug.Print "uin1(1)" & uin1(1)
If uin1(1) = onlineUser(iii).uin Then
Form1.TreeView1.Nodes(ite).Tag = onlineUser(iii).ip + "`" + onlineUser(iii).port + "`"
Form1.TreeView1.Nodes(ite).Bold = True
Form1.TreeView1.Nodes(ite).BackColor = &H80000013
'Form1.TreeView1.Nodes(i).
End If
Else: 'ite = ite + 1
End If
Next
Next iii
login1 = False
loginlist = False
End If
End Sub
如果点击好友节点,进入发送消息界面,代码如下
Private Sub TreeView1_DblClick()
Dim Index As Integer
Dim i As String
i = TreeView1.SelectedItem
'Index = TreeView1.Node.Index
g_commonUid = I ‘将用户登陆号传给发送消息界面
' MsgBox g_commonUid, vbCritical
If i <> "好友列表" Then
If TreeView1.Nodes(i).Children <= 0 And Form1.TreeView1.Nodes(i).Parent <> Form1.TreeView1.Nodes(1) Then
g_tag1 = CStr(TreeView1.Nodes(i).Tag)
Form4.Refresh
Form4.Image1.Picture = Form3.ImageList1.ListImages(TreeView1.Nodes(i).Image).Picture
Form4.Show
End If
End If
End Sub
界面主要控件如下
控件 |
命名 |
说明 |
label |
Label1 |
Caption=通讯号 |
label |
Label2 |
Caption=密码 |
label |
Label3 |
Caption=服务器 |
CommandButton |
Command1 |
Caption=登陆 |
CommandButton |
Command2 |
Caption=退出 |
CommandButton |
Command3 |
Caption=注册新用户 |
comboBox |
Combo1 |
输入服务器地址框 |
comboBox |
Combo2 |
输入通讯号框 |
text |
Text1 |
密码框 |
登陆界面如图二,用户输入登陆号和密码登陆,如果登陆出错,比如密码错误,则由回调函数ExeSysMsg传回错误信息,否则登陆成功,form2 窗体是登陆窗体,主要代码如下
Private Sub Command1_Click()
If Combo2.Text = "" Then
MsgBox "用户名不能为空", vbCritical
Combo2.SetFocus
Exit Sub
End If
If Text2.Text = "" Then
MsgBox "密码不能为空", vbCritical
Text2.SetFocus
Exit Sub
End If
Dim str() As String
str = Split(Combo1.Text, ":")
‘和服务器建立连接
SetNetworkDll str(0), str(1), "", 0, "", ""
‘调用登陆函数
Call CmdLoginDll(AddressOf ExeLoginReply, 2, Combo2.Text, "", Text2.Text)
End Sub
界面主要控件如下
控件 |
命名 |
说明 |
label |
Label1~label13 |
|
CommandButton |
Command1~ Command2 |
|
comboBox |
Combo1~ Combo5 |
|
text |
Text1~text6 |
|
imageCombo |
ImageCombo1 |
ImageCombo1.imagelist=imagelist1 |
imageList |
ImageList1 |
锁定一组图片 |
注册界面由用户通过ADO远程登录到服务器数据库,进行注册,这里有两种方式进行连接远程数据库,通过ODBC 驱动和直接通过ADO对象连接,这里通过ODBC连接,服务器ODBC 数据源DSN设为ShareRes ,并和相应数据库建立连接。,注册成功,系统返回用户注册号码。注册界面如图五
图五
代码如下
Private Sub Command1_Click()
Dim count As Integer
Dim count1 As Integer
If Text1.Text = "" Then
MsgBox "请填写用户名", vbCritical
Text1.SetFocus
Exit Sub
End If
If Text2.Text = "" Then
MsgBox "请填写密码", vbCritical
Text2.SetFocus
Exit Sub
End If
If Text6.Text = "" Then
MsgBox "请填写呢称", vbCritical
Text6.SetFocus
Exit Sub
End If
If Text7.Text = "" Then
MsgBox "请填写EMAIL", vbCritical
Text7.SetFocus
Exit Sub
End If
Dim conn As New ADODB.Connection
Dim rs_add As New ADODB.Recordset
Dim str As String
'str="Provider=Microsoft.Jet.OLEDB.4.0;data source=//127.0.0.1/e$/xyh/ÐìÓý»Ô/shareResV2.mdb"
‘服务器地址为127。0。0。用户可以改变
str = "server=127.0.0.1;dsn=ShareRes;uid=sa;pwd=sa;"
conn.Open str
If Trim(Text2.Text) <> Trim(Text3.Text) Then
MsgBox "Á½´ÎÃÜÂë²»Ò»ÖÂ", vbOKOnly + vbExclamation, ""
Text2.SetFocus
Text3.Text = ""
Text2.Text = ""
Else
sql = "select * from UserBrief"
rs_add.Open sql, conn, adOpenKeyset, adLockPessimistic
'count = rs_add.RecordCount
rs_add.MoveLast
count = rs_add.Fields(0)
rs_add.AddNew
count1 = count + 1
rs_add.Fields(0) = count + 1
rs_add.Fields(1) = Text2.Text
rs_add.Fields(2) = Text1.Text
rs_add.Fields(4) = Combo5.Text
rs_add.Fields(5) = Combo4.Text
rs_add.Fields(11) = ImageCombo1.SelectedItem.Index
If Combo2.Text = "ÄÐ" Then
rs_add.Fields(12) = True
Else
rs_add.Fields(12) = False
End If
rs_add.Fields(13) = Text6.Text
rs_add.Fields(16) = Text5.Text
rs_add.Fields(17) = Combo3.Text
rs_add.Fields(18) = Text7.Text
rs_add.Update
rs_add.Close
MsgBox "添加用户成功", vbOKOnly + vbExclamation, ""
MsgBox "你的号码是:" & count1, vbOKOnly + vbExclamation, ""
Form3.Visible = False
End If
conn.Close
End Sub
界面主要控件如下
控件 |
命名 |
说明 |
label |
Label1 |
Caption=发送信息至 |
CommandButton |
Command2 |
发送按钮 |
frame |
Frame1~frame2 |
|
text |
Text1~text2 |
Text1在frame1里Text2在frame2 里 |
image |
Image1~image2 |
显示用户图像 |
发送消息界面如图四,用户在下面文本框里输入文字点击发送按钮,便可发送消息。如果用户不在线,点击发送按钮则消息存入服务器留言表数据库。用户收到消息由ExeGetMsg函数完成,用户可以在函数里作任何事
发送消息的代码如下
Private Sub Command2_Click()
If g_sendMessage = False Then
Dim string1() As String
If CStr(g_tag1) <> "" Then ‘如果没有收到消息,从相应树的节点中取发送对象ip地址
string1 = Split(CStr(g_tag1), "`")
g_stSelUser.sIP = CStr(string1(0))
g_stSelUser.nPort = string1(1)
End If
' MsgBox "''''''''''''''", vbCritical
Debug.Print g_stSelUser.sIP
' Debug.Print sendUin1.ip
Debug.Print g_stSelUser.nPort
Else
'g_sendMessage = False
End If
''''''''''''''''''''''''''''''''''''''''''''''''''''
If Text2.Text = "" Then
Exit Sub
End If
Text1.Text = Text1.Text + "说:" + Text2.Text + " " + CStr(Now) + Chr(13) + vbCrLf
'MsgBox str(1), vbCritical
If g_sendMessage = True Or CStr(g_tag1) <> "" Then ‘判断ip 地址是否为空,为空说明用户不在线调用留言函数
MsgBox g_stSelUser.sIP
Call CmdSendMsgDll(MSG_TEXT, WITH_FIREWARE, 0, g_stSelUser.uin, g_stSelUser.sIP, g_stSelUser.nPort, Text2.Text + " " + CStr(Now))
Else
MsgBox "liuyan"
Call CmdLeaveMsgDll(MSG_TEXT, 0, g_stSelUser.uin, Text2.Text)
End If
Text2.Text = ""
End Sub
公用模块里声明全局变量,声明用到DllShareRes.dll函数,及回调函数,由于函数众多,读者可看源程序
1.需要注意的是CmdLoginDll函数的第二个参数是防火墙状态,此值设置为0,即未定义即可
2.由于服务器是以 异步方式工作,所以各个回调函数没有固定的顺序返回,先后顺序不一定是调用的先后顺序
3.回调函数里的parm参数是一字符串,包含有用户各种信息,中间以“`”隔开,因此用户名,用户资料等不能允许使用`符号,否则客户会导致客户端死机。
4.用户最好在回调函数里处理数据,那样出错情况较少。
5.用户状态改变由CmdStatChangeDll(AddressOf ExeUserOnline, STATUS_OFFLINE)函数调用ExeUserOnline回调函数完成