首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

socket 通讯 并发 有关问题

2012-04-01 
socket 通讯 并发 问题客户端通过socket与主机进行通讯,如果多个用户同时向主机发送数据,则返回结果是错误

socket 通讯 并发 问题
客户端通过socket与主机进行通讯,如果多个用户同时向主机发送数据,则返回结果是错误的,网上查了一些资料,说是数据并发的问题,现在我改怎样改进,才能不致数据错误。
服务端是UNIX C,客户端是vb.net,现把客户端代码贴出来,大家看我看下,该如何改进,才能满足要求。
客户端代码:

VB.NET code
Public Class StateObject    'SOCKET ID    Public workSocket As Socket = Nothing    '可接收数据大小    Public Const BufferSize As Integer = 1024 * 512    'Public Const BufferSize As Integer = 1024    '接收数据缓冲区    Public buffer(BufferSize) As Byte    '接收数据    Public sb As New StringBuilderEnd ClassPublic Class ESA_TCP_CLIENT    '处理结果    Public Enum ExSocketState        ExSocketSucceed = 0     '处理成功        ExSocketNoConnect = 1   '主机无连接        ExSocketUnKnown = 2     '未知状态(主机未响应)        ExSocketAllUsed = 3     '无可用端口(没有空闲状态的端口)    End Enum    Private connectDone As New ManualResetEvent(False)    Private sendDone As New ManualResetEvent(False)    Private receiveDone As New ManualResetEvent(False)    Private response As String = String.Empty    '超时时间(毫秒)    Private iTimeOutM As Integer    Private isConn As Boolean = False    Public Function SendTo(ByVal strHostIP As String, _                           ByVal iPort As Integer, _                           ByVal iTimeout As Integer, _                           ByVal strSend As String, _                           ByRef strRecv As String, _                           ByVal Merch_ID As String, _                           ByVal ULNm As String) As ExSocketState   '增加Merch_ID,ULNm zfy 2011-1-6 用于生成Merch_ID.txt文件        On Error GoTo go_Err        Dim ipHostInfo As IPHostEntry = Dns.GetHostEntry(strHostIP)        Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)        Dim remoteEP As New IPEndPoint(ipAddress, iPort)        Dim client As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)        strRecv = ""        If iTimeout > 0 And iTimeout < 200000 Then   '1000000            iTimeOutM = iTimeout        Else            iTimeOutM = 5000    '5000        End If        SendTo = ExSocketState.ExSocketUnKnown        client.BeginConnect(remoteEP, New AsyncCallback(AddressOf ConnectCallback), client)        Dim s2 = Now()        If connectDone.WaitOne(iTimeOutM, False) = True Then            If isConn = True Then                Send(client, strSend, Merch_ID, ULNm)  '增加Merch_ID zfy 2011-1-6 用于生成Merch_ID.txt文件                If sendDone.WaitOne(iTimeOutM, False) = True Then                    If isConn = True Then                        '由于测试中出现异步通讯时接收主机报文有报文不完整情况                        '所以在此处修改为在连接、发送时采用异步方式,而接收数据时采用同步方式                        '此处还需要考虑同步接收的超时机制,暂略                        Dim state As New StateObject                        state.workSocket = client                        If Receive(state, Merch_ID, ULNm) Then    '增加Merch_ID,ULNm zfy 2011-1-6 用于生成Merch_ID.txt文件                            'If Receive() Then                            strRecv = state.sb.ToString()                            If strRecv.Length > 10 Then                                strRecv = strRecv.Substring(10, strRecv.Length - 10)                            Else                                strRecv = ""                            End If                            SendTo = ExSocketState.ExSocketSucceed                        Else                            SendTo = ExSocketState.ExSocketUnKnown                        End If                    Else                        SendTo = ExSocketState.ExSocketUnKnown                    End If                    Else                        SendTo = ExSocketState.ExSocketUnKnown                    End If            Else                SendTo = ExSocketState.ExSocketNoConnect            End If        Else            SendTo = ExSocketState.ExSocketNoConnect        End Ifgo_Exit:        If client.Connected = True Then            client.Shutdown(SocketShutdown.Both)        End If        client.Close()        Exit Functiongo_Err:        GoTo go_Exit    End Function    Private Sub ConnectCallback(ByVal ar As IAsyncResult)        On Error GoTo go_Err        Dim client As Socket = TryCast(ar.AsyncState, Socket)        If client IsNot Nothing Then            client.EndConnect(ar)            isConn = client.Connected        Else            isConn = False        End If        connectDone.Set()go_Exit:        Exit Subgo_Err:        isConn = False        connectDone.Set()        GoTo go_Exit    End Sub    Private Function Receive(ByRef state As StateObject, ByVal Merch_ID As String, ByVal ULNm As String) As Boolean    '增加Merch_ID,ULNm zfy 2011-1-6 用于生成Merch_ID.txt文件        On Error GoTo go_Err        Dim readStream As New NetworkStream(state.workSocket)        Dim blnReturn As Boolean = False        Dim intRcv As Integer        Dim strTmp As String = ""        state.buffer.Clear(state.buffer, 0, StateObject.BufferSize)        readStream.ReadTimeout = iTimeOutM        intRcv = readStream.Read(state.buffer, 0, StateObject.BufferSize)        Do While intRcv > 0            strTmp = Encoding.Default.GetString(state.buffer, 0, intRcv)            state.sb.Append(strTmp)            If ConfigurationManager.AppSettings("g_IsDebug") = "1" Then                Dim FileToWrite As System.IO.FileStream = System.IO.File.Create("D:\程序\ESA_OPR_New\debug\Receive" + Merch_ID + "_" + ULNm + ".txt")                Dim rByte() As Byte = Encoding.Default.GetBytes(state.sb.ToString.ToCharArray)                FileToWrite.Write(rByte, 0, rByte.Length)                FileToWrite.Close()                FileToWrite = Nothing            End If            '不按照报文头字符长度来取报文体字段,因为在测试中发现WINDOWS与UNIX在中文和特殊字符的长度判断上不相同            '所以采用查找结束符号的方式来判断报文尾            If InStr(strTmp, "</PACKAGE>") > 0 Then                Exit Do            Else                state.buffer.Clear(state.buffer, 0, StateObject.BufferSize)                intRcv = readStream.Read(state.buffer, 0, StateObject.BufferSize)            End If        Loop        blnReturn = True        readStream = Nothinggo_Exit:        Return blnReturn        Exit Functiongo_Err:        blnReturn = False        GoTo go_Exit    End Function    Private Sub Send(ByVal client As Socket, ByVal data As String, ByVal Merch_ID As String, ByVal ULNm As String)   '增加Merch_ID,ULNm 2010-1-6 zfy        On Error GoTo go_Err        '2011-7-14 解决中文字符编码数量问题        Dim strLen As Integer        For n = 1 To data.Length            If AscW(Mid(data, n, 1)) > 256 Then strLen = strLen + 2 Else strLen = strLen + 1        Next        data = Format(strLen, "0000000000") & data        If ConfigurationManager.AppSettings("g_IsDebug") = "1" Then            Dim FileToWrite As System.IO.FileStream = System.IO.File.Create("D:\程序\ESA_OPR_New\debug\Send" + Merch_ID + "_" + ULNm + ".txt")            'Dim rByte() As Byte = Encoding.Default.GetBytes(data.ToCharArray)            Dim rByte() As Byte = Encoding.Default.GetBytes(data.ToCharArray)            FileToWrite.Write(rByte, 0, rByte.Length)            FileToWrite.Close()            FileToWrite = Nothing        End If        Dim byteData As Byte() = Encoding.Default.GetBytes(data)         '2011-7-15 zfy 解决报文发送乱码问题        client.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), client)go_Exit:        Exit Subgo_Err:        GoTo go_Exit    End Sub    Private Sub SendCallback(ByVal ar As IAsyncResult)        On Error GoTo go_Err        Dim client As Socket = TryCast(ar.AsyncState, Socket)        If client IsNot Nothing Then            isConn = True            Dim bytesSent As Integer = client.EndSend(ar)        Else            isConn = False        End If        sendDone.Set()go_Exit:        Exit Subgo_Err:        isConn = False        sendDone.Set()        GoTo go_Exit    End SubEnd Class 



[解决办法]
"如果多个用户同时向主机发送数据,则返回结果是错误"

这意味着单个用户访问是没问题的,这意味着单个用户发送是没问题的,看你的代码需要连接,说明是TCP/IP协议,因为每一个TCP/IP协议都是通过一个套接字连接,一个套接字获取或发送数据,如果单个的成功了,也就意味着客户端应该是没问题的,所以从通讯技术上,我认为问题应该出在服务器那边,而不是客户端。

但如果问题出在握手协议或具体数据上,除非你给出握手协议标准和相关算法,否则别人也很难帮你猜问题在哪。还有,你的是一个类,至于出问题的是在过程调用?数据算法?还是握手协议?都很难估计。但单纯以问题出现的情况来看,服务器端的嫌疑最大,你这问题看来还要自己琢磨一下,因为具体的问题出在哪很难帮你去猜。
[解决办法]
我想你的服务端处理数据需要时间而客户端发送间隔太短,socket被挂起无法响应新的请求
可能与你的服务端程序有关。

网络并发是一个很有意思的课题。

热点排行