用WinSock控件编写聊天室软件碰到的几个问题,希望大家指教。

StarLittle 2000-01-17 10:27:00
因为就是写着玩,所以基本思路很简单,一个服务器端程序,一个客户端程序。所有客户发出的消息都发给服务器,服务器再转发给相应客户,或是所有客户。实际编写中碰到了几个问题:
1, 当连接两个或两个以上客户时,只有最后一个客户能很快更新,而前面的客户更新巨慢,而且我看着好象是它把好几条信息合并成了一条信息。比如说别的客户发了三条信息,应该是三行,到前面的客户时却把三条信息合到了一行上。我可以肯定的是他一定是只触发了一次客户的DataArrival事件。在调试中,我发现了令我困惑的一个问题,那就是有时服务器SendData时并没有立刻触发客户的DataArrival。比如说在新建客户连接时要更新以前客户的在线用户的列表。我的做法是在Accept以后,对各个客户先发一个清除用户列表的消息,怪,没有触发客户端程序的DataArrival,我认为并不是速度问题,因为我在这停了一下,以局域网的速度很快就该到了,而当我走到下一个SendData时一并触发了。
2, WinSock的Close事件是怎么写的?我在服务器端的Close里写了一些代码,客户端关闭时触发,结果他好象是反复执行,跟死循环一样。非要我在Close事件里显式的调用一下Close方法才能搞定。它就是这样写的吗?
3, RemoteHost怎么只能返回空,害的我图省事只能显示ID
...全文
305 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
skt642 2001-05-31
  • 打赏
  • 举报
回复
16522关注!
dirotac 2000-11-13
  • 打赏
  • 举报
回复
有四个请求
1,2,3,4
其中
2,3,4
是在1,得处理过程当中进来的
当执行完1的处理后
2,3,4的处理顺序是4,3,2,
总是先处理后进来的请求
导致了先进来的请求被一直挂起
这很不理想
我也遇到这样的事
关注
希望得到答案
jing 2000-01-19
  • 打赏
  • 举报
回复
SERVER:
Dim intMax As Long
Dim i As Long
Dim D(10000) As String 'storage data



Private Sub cmdRefresh_Click()
DEServer.rscmdUserlist.Close
DEServer.rscmdUserlist.Open
Set DataGrid1.DataSource = DEServer
DataGrid1.DataMember = "cmdUserlist"
End Sub

Private Sub Form_Load()
intMax = 0
tcpServer(0).LocalPort = 2888
tcpServer(0).Listen

End Sub





Private Sub tcpServer_ConnectionRequest(Index As Integer, ByVal requestID As Long)
Dim oWsk
If Index = 0 Then 'discrimination Winsock have closeed
For Each oWsk In Me.Controls
If TypeOf otext Is Winsock Then
Debug.Print otext.State
If oWsk.State = sckClosed Or otext.State = sckClosing Then
oWsk.Close
oWsk.Accept requestID
Exit Sub
End If
End If
Next

intMax = intMax + 1
Load tcpServer(intMax)
tcpServer(intMax).LocalPort = 0
If tcpServer(intMax).State <> sckClosed Then tcpServer(intMax).Close
tcpServer(intMax).Accept requestID


End If
End Sub



Private Sub tcpServer_DataArrival(Index As Integer, ByVal bytesTotal As Long)
On Error Resume Next
Dim k As Integer
Dim Mg As String
Mg = ""
tcpServer(Index).GetData D(Index)
txtTalk.Text = txtTalk.Text & vbNewLine + CStr(Date) + CStr(Time()) + " " + D(Index)
If Mid(D(Index), 1, 1) = "B" And Mid(D(Index), Len(D(Index)), 1) = "%" And Len(D(Index)) > 2 Then
If DEServer.rscmdUsertable.State = 1 Then
DEServer.rscmdUsertable.Close
End If
DEServer.rscmdUsertable.Open
DEServer.rscmdUsertable.MoveFirst

DEServer.rscmdUsertable.Find ("User_Name= '" & Mid(D(Index), 2, Val(Len(D(Index)) - 2)) & "'")
If Not DEServer.rscmdUsertable.EOF Then
For k = 3 To DEServer.rscmdUsertable.Fields.Count - 1
Mg = Mg + CStr(DEServer.rscmdUsertable.Fields(k))
Next
Mg = "B" + Mg + "%"
If optAll.Value = True Then
For i = 1 To intMax
'Debug.Print "Send Data to client" & Str(i)
DoEvents
tcpServer(i).SendData Mg
Next
Else
DoEvents
tcpServer(Index).SendData Mg
End If
Else
DoEvents
tcpServer(Index).SendData ".."
End If
Else
DoEvents
tcpServer(Index).SendData ".."
End If
D(Index) = ""
End Sub

CLient:
Private Sub cmdConnect_Click()
On Error GoTo errd:
tcpClient.Close
tcpClient.RemoteHost = txtServer.Text
tcpClient.RemotePort = 1001
tcpClient.Connect
cmdConnect.Enabled = False
Exit Sub
errd:
MsgBox Err.Description

End Sub

Private Sub Command1_Click()
frmClient1.Show
End Sub

Private Sub Form_Load()
'tcpClient.RemoteHost = "Jing"
'tcpClient.RemotePort = 1001
End Sub

Private Sub tcpClient_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
Debug.Print "1 Receive Sever information" + Str(bytesTotal)
tcpClient.GetData strData
txtTalk.Text = txtTalk.Text & strData
Debug.Print tcpClient.State

End Sub

Private Sub Text1_Change()

End Sub

Private Sub txtSendData_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then
tcpClient.SendData CStr(tcpClient.LocalHostName) & ": " & txtSendData.Text & vbNewLine
Debug.Print tcpClient.State
txtSendData.Text = ""

End If

End Sub


tonyhan 2000-01-19
  • 打赏
  • 举报
回复
其实Msdn中就有你这样的利子,应该是在sdksample\winsock.
littletao 2000-01-19
  • 打赏
  • 举报
回复
如果对响应速度要求不是特别特别高的话,我觉得接受到数据后
最好还是应答一下,以保持数据的正确性。而且,可以解决你
的问题。
jing 2000-01-18
  • 打赏
  • 举报
回复
你可根据winsock.state的返回值.
jing 2000-01-18
  • 打赏
  • 举报
回复
你忘了DoEvents了吗?
StarLittle 2000-01-18
  • 打赏
  • 举报
回复
综合littletao和jing所说,我想是不是应该这样作:在SendData之后,循环调用DoEvents,
在SendComplete事件里改变状态以跳出循环.但是这样速度就会快吗?因为在公司我在几台机子之间转了几个圈,也没见它刷新.
littletao 2000-01-18
  • 打赏
  • 举报
回复
1因为senddata时会对发送数据包进行重新组合,所以几条senddata语句
合并成一个包是很正常的。解决方法是:
senddata后等待对方连接响应,而对方每次收到正确数据后,再发个回音消息
等待方接收到回音消息后再继续发下面的数据。这就相当于一次握手确认过程,
在internet编程里经常用到,象telnet就有3次握手过程。socket比telnet,http
更底层,所以得自己保证数据的正确性。
3 try remotehostip应该就可以了。
StarLittle 2000-01-17
  • 打赏
  • 举报
回复
不好意思,第二点是我自己搞错了.WinSock的Close事件是远端控件关闭时触发,而不是他本身关闭时触发.

1,451

社区成员

发帖
与我相关
我的任务
社区描述
VB 控件
社区管理员
  • 控件
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧