




已阅读5页,还剩26页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
华南农业大学理学院课程实验(设计)报告专业年级: 11信息与计算科学 学生学号: 201130760 学生学号: 201130760 学生姓名: 学生姓名: 实验题目: Socket应用程序设计 指导老师: 实验时间:2013年11月1日-2013年11月29日目 录1实验内容和要求11.1实验内容11.2实验要求11.3实验实现的功能12实验过程22.1系统需求分析22.1.1客户端22.1.2服务器22.2系统的概要设计32.3具体实现42.3.1客户端42.3.1.1登陆功能42.3.1.2聊天功能62.3.1.3离线聊天功能82.3.1.4接受离线信息功能92.3.1.5聊天记录功能102.3.1.6显示用户状态功能122.3.1.7文件传输功能132.3.2服务器192.3.2.1登录、注册验证功能192.3.2.2群聊功能212.3.2.3用户信息管理功能213实验结果234讨论与总结245参考文献246小组分工251实验内容和要求1.1实验内容在学习完TCP/IP协议组后,要求掌握基于此协议实现网络通信,理解TCP与UDP的不同特征以及实现方式。基于Windows平台建立一个基于TCP/IP协议的网络通讯小应用,实验可采用UDP或TCP实现。1.2实验要求(1)能够进行用户管理,所有用户必须登录到服务器,有服务器维护在线信息;(2)IM功能:用户登录后能够进行实时多方点到点短信息通信,如聊天;(3)能够选择要求服务器进行转发服务;(4)能够保存通信记录到数据库(SQL Server或者其他桌面型数据库或数据文件);(5)能进行双方文件传输,能够显示进度;*(6)支持断点重传,检查时需有功能随时中断传送,并在下次启动时能显示重传状态;*(7)数据包加密;*(8)实时语音双向传送功能;*(9)多方通话功能;(10)界面设计要求布局合理,信息清晰。(11)自加功能。(*为选做内容)1.3实验实现的功能(1)服务器能够进行用户管理,所有用户必须登录到服务器,有服务器维护在线信息;(2)IM功能:用户登录后能够进行实时多方点到点短信息通信,如聊天;(3)服务器离线转发功能;(4)客户端保存群聊天记录;(5)能进行双方文件传输,能够显示进度;(10)界面设计要求布局合理,信息清晰。2实验过程2.1系统需求分析2.1.1客户端(1)登陆功能:在用户填写相关的账户和密码时,客户端能够发送连接客户端要求,当,连上客户端的时候,客户端能够将账号和密码信息发送到服务器进行核对,并返回信心(2)聊天功能:在客户端中,用户有权选择群聊还是与某在线用户私聊(3)离线聊天功能:在线的用户可能通过服务器将信息发给离线的用户(4)接受离线信息共能:当用户上线时,接收其他用户的离线信息(5)聊天记录功能:客户端能自动将群聊的信息保存在相应的数据库当中(6)显示用户状态功能:对于在线的用户和离线的用户能够及时显示在表格当中2.1.2服务器(1)维护用户功能:添加新用户,修改用户密码,删除用户(2)更新用户状态功能:通知客户端更新成员状态和相应的列表(3)离线功能:为离线用户保存离线信息,并且在用户上线的时发送相应的离线信息(4)检验用户信息功能:验证用户的账号和密码的正确性,并禁止用户异地同时登陆(5)显示群聊记录:在服务器中几时显示群聊的信息2.2系统的概要设计图2.1软件功能模块图图2.2服务器与客户端功能的设计图2.3服务器与客户端数据流程图2.3具体实现2.3.1客户端2.3.1.1登陆功能图2.4登陆界面(1)在按下登陆按钮的时候,程序获取界面中的服务器中IP地址和端口号,同时检验账号和密码是否有误。若账号和密码填写上没有错误,进行连接服务器。代码如下:Private Sub Command1_Click() 点击登陆按钮 Form2.login = False 设置能否登陆标志为“不能” If Form1.Username.Text = Or Form1.Usercode.Text = Then 检查账号和密码填写是否有空 MsgBox 请输入账号和密码 Else Call tcpClient_Connect 连接服务器 DoEvents If Form2.tcpClient.State = 7 Then 若连接上服务器则发送账号和密码 Form2.tcpClient.SendData | & * & Form1.Username.Text & * & # & Form1.Usercode.Text & # & | *账号*#密码# DoEvents Else MsgBox 没有服务器 End If Timer1.Enabled = True End IfEnd SubPublic Sub tcpClient_Connect() If Form2.tcpClient.State 7 Then Form2.tcpClient.Close Form2.tcpClient.RemoteHost = Form1.txtHost.Text Form2.tcpClient.RemotePort = Form1.txtPort.Text Form2.tcpClient.Connect DoEvents End IfEnd Sub(2)当连接成功后,发送账号和密码,用相关的已经定义好协议进行封装发送给服务器。协议是*账号*#密码#代码如下:If Form2.tcpClient.State = 7 Then 若连接上服务器则发送账号和密码 Form2.tcpClient.SendData | & * & Form1.Username.Text & * & # & Form1.Usercode.Text & # & | *账号*#密码#(3)当客户端收到的服务器的协议信息是密码和账号是正确的时候才能进行真正的登录。协议是:当收到*#时,代表登录成功。当收到*ERROR时,代表没有这账号。当收到#ERROR时,代表密码错误。当收到*ONLINE时,代表账号已经登录。代码如下:If InStr(sData, *#) 0 Then login = True ElseIf InStr(sData, *ERROR) 0 Then MsgBox 没有这账号 ElseIf InStr(sData, #ERROR) 0 Then MsgBox 密码错误 ElseIf InStr(sData, *ONLINE) 0 Then MsgBox 账号已经登录End If2.3.1.2聊天功能(1)群聊天。在图2.2的文本框中输入字符,便可以发送信息。发送的协议:$群聊天信息$,通过进行过协议封装的聊天信息,能够让服务器进行识别,别且转发给在线用户。图2.5聊天窗口Private Sub cmdSend_Click() If txtOut.Text = Then MsgBox 发送内容不能为空 Exit Sub End If tcpClient.SendData $ + Form1.Username.Text + : & txtOut.Text + $ =插入聊天记录 a = CStr(Now() + Chr(10) + Form1.Username.Text + : + txtOut.Text + Chr(10) Set rs = cn.Execute(insert into data (tcp_data) values ( & a & ) tcp_data是表的列名 =插入聊天记录 rtbIn.Text = rtbIn.Text & Chr(10) + CStr(Now() + Chr(10) + Form1.Username.Text + : + txtOut.Text + Chr(10) txtOut.Text = rtbIn.SelStart = Len(rtbIn.Text)End Sub(2)发送私聊信息。在listviews中点击相应的用户名字就可以进行私聊,在登陆的时候已经设置好TCP控件的端口号。代码如下:Public Sub set_privatechat() For i = 1 To Form2.ListView1.ListItems.Count Private_Chat(i).ClientSer.Close Private_Chat(i).ClientSer.LocalPort = 8080 + i Private_Chat(i).ClientSer.Listen NextEnd Sub(3)接收在线私聊信息。Private Sub ClientCli_DataArrival(ByVal bytesTotal As Long) ClientCli.GetData str, vbString Text1.Text = Text1.Text & str Text1.SelStart = Len(Text1.Text) If Me.WindowState = 1 Then Timer2.Enabled = True End IfEnd SubPrivate Sub ClientSer_DataArrival(ByVal bytesTotal As Long) ClientSer.GetData str, vbString Text1.Text = Text1.Text & str Text1.SelStart = Len(Text1.Text) If Me.WindowState = 1 Then Timer2.Enabled = True End IfEnd Sub2.3.1.3离线聊天功能在输入框中输入私聊信息时,先判断是否在线,假如是在线的话直接利用已经和对方连接的TCP控件进行发送信息。假如是离线用户的话,利用协议将封装好的离线信息发送给服务器,在通过服务器发送给离线的用户。离线信息协议:%*1发送者账号*1*2接收者账号*2*$离线的信息*$%代码如下:Private Sub Command1_Click() Dim str As String If Len(Text2.Text) = 0 Then MsgBox (发送内容不能为空!) Exit Sub End If str = Form1.Username.Text & & Time & Chr(13) & Chr(10) & Text2.Text str = str & Chr(13) & Chr(10) & Chr(13) & Chr(10) If ClientSer.State = 7 Then ClientSer.SendData str MsgBox 已连接上对方 ElseIf ClientCli.State = 7 Then ClientCli.SendData str End If If ClientCli.State 7 And ClientSer.State 7 Then 离线信息设置 Form2.tcpClient.SendData % + *1 + Label2.Caption + *1 + *2 + Label3.Caption + *2 + *$ + str + *$ + % DoEvents End If Text1.Text = Text1.Text & str Text1.SelStart = Len(Text1.Text) Text2.Text = End Sub图2.6私聊对话框2.3.1.4接受离线信息功能接收离线私聊信息。当收到服务器的离线信息时,对发送过来的字符串进行信息提取,提取出发送者、接收者和信息。Function check_outlinemessage(message As String) sender_where1 = 0 reciever_where1 = 0 outmessage_where1 = 0 sender_where2 = 0 reciever_where2 = 0 outmessage_where2 = 0 If InStr(message, *2) 0 Then Do sender_where1 = InStr(sender_where2 + 1, message, *1) sender_where2 = InStr(sender_where1 + 1, message, *1) sender = Mid(message, sender_where1 + 3, sender_where2 - sender_where1 - 3) outmessage_where1 = InStr(outmessage_where2 + 1, message, *$) outmessage_where2 = InStr(outmessage_where1 + 1, message, *$) outmessage = Mid(message, outmessage_where1 + 4, outmessage_where2 - outmessage_where1 - 4) For n = 1 To Form2.ListView1.ListItems.Count If Form2.ListView1.ListItems(n).Text = sender Then Private_Chat(n).Text1.Text = Private_Chat(n).Text1.Text & outmessage Private_Chat(n).Text1.SelStart = Len(Private_Chat(n).Text1.Text) Form2.ListView1.ListItems(n).ForeColor = vbRed Form2.ListView1.ListItems(n).ListSubItems.Item(1).ForeColor = vbRed Form2.ListView1.ListItems(n).ListSubItems.Item(2).ForeColor = vbRed End If Next Loop Until InStr(sender_where2 + 1, message, *1) = 0 End IfEnd Function2.3.1.5聊天记录功能(1)读取数据库中的聊天信息。添加VB的控件ADO,ADO控件建立起读取聊天记录的桌面型数据库access,读取数据库中信息,如图2.4。代码如下:Public cn As ADODB.ConnectionPublic rs As ADODB.RecordsetSub adddata()Set cn = New ADODB.Connectioncn.ConnectionString = Provider=Microsoft.Jet.OLEDB.4.0;Data Source= & App.Path & data.mdb;Persist Security Info=Falsecn.OpenSet rs = cn.Execute(select * from data)End Sub图2.7数据库的信息当按下群聊天记录的时候弹出对应的RichTextBox控件如下图图2.8群聊天记录对话框(2)将群聊天信息加入到数据库。提取$与$之间的群聊天信息 If InStr(sData, $) 0 Then group_chat1 = InStr(sData, $) group_chat2 = InStr(group_chat1 + 1, sData, $) ssData = Mid(sData, group_chat1 + 3, group_chat2 - group_chat1 - 3) =插入聊天记录 a = CStr(Now() + Chr(10) + ssData + Chr(10) Set rs = cn.Execute(insert into data (tcp_data) values ( & a & ) tcp_data是表的列名 =插入聊天记录 rtbIn.Text = rtbIn.Text + Chr(10) + CStr(Now() + Chr(10) + ssData + Chr(10) rtbIn.SelStart = Len(rtbIn.Text) End If Call check_useronline(sData)Call set_privatechat2.3.1.6显示用户状态功能(1)当用户登录的时候,服务器会发送当前用户列表的信息给客户端,协议为*用户名*IP地址,当IP地址为NULL时,客户端识别为没有上线,只有不是NULL的时候才是真正有上线,对于上线的用户,在listview中的状态会由0变为1,表示已经上线。同时会清空listview,将所以的用户进行重新的加载。如图2.6.代码如下:Public Sub check_useronline(gData As String) account_where1 = 0 IP_where1 = 0 account_where2 = 0 IP_where2 = 0 If InStr(gData, *) = 1 Then Form2.ListView1.ListItems.Clear 清空列表 Do account_where1 = InStr(account_where2 + 1, gData, *) account_where2 = InStr(account_where1 + 1, gData, *) Username = Mid(gData, account_where1 + 3, account_where2 - account_where1 - 3) IP_where1 = InStr(IP_where2 + 1, gData, ) IP_where2 = InStr(IP_where1 + 1, gData, ) UserIP = Mid(gData, IP_where1 + 3, IP_where2 - IP_where1 - 3) Set itmx = Form2.ListView1.ListItems.Add(1, , Username) itmx.SubItems(2) = UserIP If UserIP NULL Then itmx.SubItems(1) = 1 Else itmx.SubItems(1) = 0 End If Loop Until InStr(account_where2 + 1, gData, *) = 0 End IfEnd Sub 图2.9用户状态列表(2)当用户退出的时候,会发送Q的字符串给服务器,告诉服务器退出,并且让服务器发送用户状态信息给各个在线用户,再次刷新用户。代码如下:Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) tcpClient.SendData Q & CStr(Now() DoEvents Unload Form3 Unload Form2 Form1.ShowEnd Sub2.3.1.7文件传输功能基于TCP/IP协议的通信,需要分别建立客户端应用程序和服务器段应用程序,大致流程如图4-1 图2.10客户端与服务器数据流图实现原理:发送方先获取待传输文件的基本信息,主要是文件名及文件长度(用于创建数据缓冲区);然后,将其发送给接收方;接着,建立和文件一样大小的数据缓冲区,并将文件读入;最后,将数据缓冲区中的数据发送给接收方。与此同时,当接收方接收到文件名和文件长度之后,就为其创建新的文件和数据缓冲区;然后,接收传输的文件数据,并将其放在数据缓冲区中;最后,依次将数据缓冲区的数据写入新创建的文件中。这样便完成了不同计算机之间的文件传输。在本次实验中,于私人聊天模式里,当勾上“打开文件传输通道后”,右边button将变为可用,如下图:,图2.11文件传输此时点击“发送文件”按钮,便会弹出窗体图2.12文件传输界面这时窗体里的winsock控件(数组)将处于监听状态,执行代码如下For j = 1 To Form2.ListView1.ListItems.Count Private_send(j).wskServer.Close Private_send(j).wskServer.LocalPort = 8000 + j Private_send(j).wskServer.ListenNext j并且若此时点击“浏览”时,将会调用系统里的控件“Comdlg”,执行下段代码Private Sub Command1_Click()With Comdlg .CancelError = True On Error GoTo OpenErr .DialogTitle = “打开一个测试文件” .Filter = “所有文件 (*.*)|*.*” .Flags = &H4 .ShowOpen Text3.Text = .FileNameEnd WithOpenErr:End Sub若此时选择的文件正确(路径,文件存在),将可以点击“发送按钮”,已连接的对方的winsock将会发生”请求”事件,接受“请求”的话,将发生“数据到达”,相关代码如下所示: Private Sub wskServer_ConnectionRequest(ByVal equested As Long)If Private_send(SelectNo).wskServer.State sckClosed Then Private_send(SelectNo).wskServer.Close Private_send(SelectNo).wskServer.Accept equestedList1.ClearList1.AddItem “已连接”Command2.Enabled = TrueEnd SubPrivate Sub wskServer_DataArrival(ByVal bytesTotal As Long)Dim WskChat As StringPrivate_send(SelectNo).wskServer.GetData WskChatIf WskChat = “NoThanks” Then MsgBox “对方拒收你发送的文件.”, vbExclamation, “Server”ElseIf WskChat = “OkSend” Then MsgBox “对方接受了你的文件.” & vbCrLf & vbCrLf & “单击“确定”开始传送”, vbInformation, “Server” GetFileNum = FreeFile LenFile = FileLen(Text3.Text) - ProBarLen = LenFile VarPlus = 0 - Open Text3.Text For Binary As #GetFileNum OnSend = True Command2.Enabled = False Call TCPSendFile(Private_send(SelectNo).wskServer, GetFileNum, SplitFile)End IfEnd Sub 若没有连接上,我们添加了Timer控件,来监控状态,若处于“连接关闭”状态,将重置winsock,并显示相应信息给用户(例如“传送”按钮不可用等),如下图:图2.13文件传输中载入文件相关代码如下: Private Sub Timer1_Timer() If Private_send(SelectNo).wskServer.State = sckClosing Then List1.Clear List1.AddItem 对方的连接已关闭. Private_send(SelectNo).wskServer.Close Private_send(SelectNo).wskServer.LocalPort = 8000 + SelectNo Private_send(SelectNo).wskServer.Listen Command2.Enabled = False End IfEnd Sub根据上面所述的原理,是使用内存来存储数据,然而,当需要传送的数据比较大时,就不能像以上介绍的那样,直接将整个文件放入数据缓冲区中了,我们的内存是无法忍受用一个几百MB甚至上GB的空间去存储那些临时数据的。显然,这种做法已远不能满足我们的需求,这时可以将文件按照一定的大小,分成若干个数据包(远小于内存的容量)。首先,设置数据包的大小(如64K),根据文件的基本信息(主要文件的长度),计算出总共需要的数据包数;然后,依次读取同数据包一样大小的数据到数据缓冲区中;接着,将数据缓冲区中的数据,发送到指定的计算机上;同时在另一端,建立一个数据缓冲区,缓冲区的大小要根据接收到的数据来确定,依次接收客户端传输过来的数据包,并将数据缓冲区的数据写入相应的文件中,这样就很容易实现大文件的传输了,这是一种较为常用的方法(较为容易实现断点续传),不过本次采用的是一种“迭代递归”的思想,使用自己编写的函数SplitFile()来稍微简单实现传输大文件,但断点重传功能将受到限制,相关代码如下:Private Function SplitFile() As Long Dim GetCount As Long If LenFile = 8192 Then GetCount = 8192 LenFile = LenFile - GetCount Else GetCount = LenFile LenFile = LenFile - GetCount End If VarPlus = VarPlus + GetCount ProBar.Value = (VarPlus / ProBarLen) * 100 SplitFile = GetCountEnd FunctionPrivate Sub TCPSendFile(objWinSock As Winsock, FileNumber As Integer, SendLen As Long) Dim FileByte() As Byte, i As Long ReDim FileByte(SendLen - 1) Get #FileNumber, , FileByte objWinSock.SendData FileByteEnd Sub至于显示进度,在私聊和传送文件窗体里,我们添加了VB自带的控件progressbar,进度也根据以传送文件的大小和总大小作简单除法:ProBar.Value = (VarPlus / ProBarLen) * 100来显示,图示效果如下:图2.14文件传输接收完毕图2.15文件传输发送完毕2.3.2服务器2.3.2.1登录、注册验证功能双击服务器.exe,进入初始界面,这里winsock将初始化,得到IP地址并且设置端口等,并对客户端管理界面进行初始化(此时该界面不显示但却已执行相关操作,点击“客户端”界面时显现):图2.16服务器界面图2.17客户端管理界面当有客户端请求连接服务器时,同意的话,发生”事件到达”,服务器采取机制:判断数据种类,并采取相关操作。代码如下:Dim sData As String Dim sName As String tcpServer(Index).GetData sData rtbSave.SelStart = Len(rtbSave.Text) 客户端向服务器发送已经登录和退出信息 = sName = Left(sData, 1) If sName = C Then tcpServer(Index).SendData C_OK DoEvents ElseIf sName = Q Then tcpServer(Index).SendData Q_OK. DoEvents Call del_IP(tcpServer(Index).RemoteHostIP) 在客服端管理中删除已退出客户端的IP地址和上线记录 tcpServer(Index).Close NumOnline = NumOnline - 1 End If = 客户端向服务器发送账号和密码,服务器提取账号和密码 = If InStr(sData, |) Then account_where1 = InStr(sData, *) account_where2 = InStr(account_where1 + 1, sData, *) user(0).uName = Mid(sData, account_where1 + 3, account_where2 - account_where1 - 3) *用户名* password_where1 = InStr(sData, #) password_where2 = InStr(password_where1 + 1, sData, #) user(0).uPWD = Mid(sData, password_where1 + 3, password_where2 - password_where1 - 3) #密码* Call check_account_pwd(Trim(user(0).uName), Trim(user(0).uPWD), Index) 校对数据库中的密码和账号是否符合 End If =2.3.2.2群聊功能因为winsock“数据到达”处理,他需要判断到达的是“登陆和退出信息”还是“已登陆用户间的群聊天记录”,这里我们做了个简单的协议“InStr(sData, $)”,相关代码如下:If InStr(sData, $) 0 Then For n = 1 To Num If tcpServer(n).State = 7 And n Index Then tcpServer(n).SendData sData DoEvents End If Next group_chat1 = InStr(sData, $) group_chat2 = InStr(group_chat1 + 1, sData, $) sData = Mid(sData, group_chat1 + 3, group_chat2 - group_chat1 - 3) rtbSave.SelStart = Len(rtbSave.Text) rtbSave.Text = rtbSave.Text + Chr(10) + CStr(Now() + Chr(10) + sData + Chr(10) rtbSave.SelStart = Len(rtbSave.Text)End If2.3.2.3用户信息管理功能这里我们采用单选按钮(添加和修改)来实现客户端管理和维护,选择注册或者删除,点击“确定后”将显示相应功能,相关代码如下:Private Sub command1_Click() Dim i, j, k As Integer If Len(Text1.Text) = 0 Then k = MsgBox(账户不能为空!, 64, 提示) Exit Sub End If If Option1.Value = True Then For i = 1 To ListView1.ListItems.Count If ListView1.ListItems(i).Text = Text1.Text Then k = MsgBox(此账户已经存在,不能添加!, 64, 提示) Exit Sub End If Next i Set itmx = ListView1.ListItems.Add(1, , Text1.Text) itmx.SubItems(1) = Text2.Text itmx.SubItems(2) = 0 ListView_Change1 = ListView_Change1 + 1 Call Data_Add(Text1.Text, Text2.Text) Call Con_Close k = MsgBox(已经添加成功!, 64, 提示) Else j = ListView1.SelectedItem.Index Form2.ListView1.ListItems(j).SubItems(1) = Text2.Text Form2.ListView1.ListItems(j).SubItems(2) = 0 Form2.ListView1.ListItems(j).SubItems(3) = ListView_Change1 = ListView_Change1 + 1 Call Data_Mod(Text1.Text, Text2.Text) Call Con_Close k = MsgBox(修改成功!, 64, 提示) Text3.Text = 0 End If Label7.Caption = ListView1.ListItems.CountEnd Sub 然而在删除层面上,服务器不能删除全部人员信息(至少得保留管理员),图2.18删除管理员账号基于这种机制,在“删除”按钮上,我们添加如下代码:Private Sub command2_Click() If Option2.Value = True Then If ListView1.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 低空经济产业园发展前景与投资价值分析
- 辽宋夏金元的经济、社会与文化-2023-2024学年高三历史二轮(专题训练)原卷版
- 激光技术工程师证书考试的质量控制与试题及答案
- 药物代谢的机制与影响试题及答案
- 轻松应对2024年系统规划与管理师考试难题试题及答案
- 马哲专业考研试题及答案
- 绞车工考试题及答案
- 计算机二级考试备考过程中的自我反思试题及答案
- 药品注册流程试题及答案
- 量身定做网络规划设计师考试试题及答案
- 苏州市公安局招聘警务辅助人员笔试真题2024
- 出版专业中级实务复习笔记
- 血液科疾病常见症状护理
- (完整版)自考00600高级英语重点上册
- 基于AI的网络安全威胁分析-全面剖析
- 2025中国铁路郑州局集团招聘614人(河南)笔试参考题库附带答案详解
- 2024年泗洪县事业单位招聘笔试真题
- 物业服务情景培训
- 2025年保安证考试答题技巧与试题解析
- 湖南省2025届高三九校联盟第二次联考英语试卷(含答案解析)
- 轨道交通智能检测技术-深度研究
评论
0/150
提交评论