Results 1 to 10 of 10

Thread: Socket Problems [Resolved]

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Aug 2002
    Location
    Belfast, N. Ireland
    Posts
    167

    Socket Problems [Resolved]

    Hi all,

    Sorry to post a big chunk of code like this and ask 'what’s wrong', it seems lazy, but I've read as much as I can find and I still can't figure out how to fix this... I'm stuck!

    I'm trying to write a client program which will send data to a server program, waits for a reply and then receives the data sent from the server.

    Here's my code, it works if I step through it slowly in debugging mode, but not if I run it normally.



    VB Code:
    1. Const READ_BUFFER_SIZE As Integer = 255
    2. Const PORT_NUM As Integer = 2100
    3.  
    4. Private client As TcpClient
    5. Private readBuffer(READ_BUFFER_SIZE) As Byte
    6.  
    7. Private Sub SendData(ByVal data As String)
    8.  
    9.         client = New TcpClient("localhost", PORT_NUM)
    10.         client.ReceiveTimeout = 500
    11.        
    12.         ' Send request to server
    13.  
    14.         Dim writer As New IO.StreamWriter(client.GetStream)
    15.         writer.Write(data & vbCr)
    16.         writer.Flush()
    17.        
    18.         ' Receive reply and display in messagebox
    19.  
    20.         Dim networkStream As NetworkStream = client.GetStream()
    21.         Dim bytes(client.ReceiveBufferSize) As Byte
    22.         Dim returndata As String
    23.  
    24.         While networkStream.DataAvailable
    25.                 networkStream.Read(bytes, 0, CInt(client.ReceiveBufferSize))
    26.                 returndata = returndata & Encoding.ASCII.GetString(bytes)
    27.         End While
    28.  
    29.         networkStream.Close()
    30.  
    31.         MsgBox(returndata)
    32.  
    33.         client.Close()
    34.         client = Nothing
    35.  
    36. End Sub

    Hopefully someone out there has some expertise with socket programming and can help me out.

    Thanks!

    Justin.

    Last edited by Justy; Aug 26th, 2003 at 03:21 AM.

  2. #2
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Justy I feel your pain... I ran into a similiar situation a few months back...

    I ultimately "fixed" it I believe using the NoDelay parameter so the data was written immediately without waiting for the buffer to fill... also, perhaps you need to increase your timeout amounts..

    VB Code:
    1. tcpClient.NoDelay = True

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Aug 2002
    Location
    Belfast, N. Ireland
    Posts
    167
    Hi nemaroller,

    Thanks for your suggestion. I've set the nodelay property but it hasn't completely fixed my problem.

    The problem seems to be that the function attempts to read what the server has sent before the server has even finished processing the message and sending it's reply. So basically it's returning nothing because it's reading too soon!

    Now, I could insert a sleep function but that would be quite inefficient and still might be not be enough time if the server decides to send a large chunk of XML for example.

    With VB6/Winsock I could handle the server response using the data received event but I don't have that luxury here.

    Does anyone else have any additional insights??

    Thanks!

    Justin.


  4. #4
    Hyperactive Member
    Join Date
    Dec 2002
    Posts
    382
    I took your example and ran it, I don't know if you have any specific reasons you wanted to use a Instance of a networkstream or a streamwriter, but if you don't, you can use this , tested it and it works fine for what you seem to want to do...


    Code:
    Imports System
    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text
    Imports System.IO
    Imports System.Threading
    
        Public HOST_NAME As String = "localhost"
        Public PORT_NUM As Int32 = 5050
        Public Client As TcpClient = Nothing
        Public PacketSize As Int32 = 512
    
        Private Sub SendData(ByVal data As String)
    
            Dim Buffer As Byte() = Nothing
    
            Try
                'Connect and send the data
                Client = New TcpClient(HOST_NAME, PORT_NUM)
                Buffer = Encoding.ASCII.GetBytes(data)
                Client.GetStream.Write(Buffer, 0, Buffer.Length)
    
                'Receive the data
                ReDim Buffer(PacketSize - 1)
                Dim SB As New StringBuilder
                Dim ByteCount As Int32
    
                'Get the data
                ByteCount = Client.GetStream.Read(Buffer, 0, PacketSize)
                SB.Append(Encoding.ASCII.GetString(Buffer, 0, ByteCount))
    
                'If more data is being send (big packet)
                While Client.GetStream.DataAvailable
                    ByteCount = Client.GetStream.Read(Buffer, 0, PacketSize)
                    SB.Append(Encoding.ASCII.GetString(Buffer, 0, ByteCount))
                End While
    
                'Show the text
                MsgBox(SB.ToString)
    
                'Shut it down
                Client.Close()
    
            Catch ex As Exception
            End Try
    
        End Sub
    Last edited by Hinder; Aug 19th, 2003 at 03:21 PM.

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Aug 2002
    Location
    Belfast, N. Ireland
    Posts
    167
    Thanks hinder!

    I also removed the StreamWriter from the server side and everything is working as expected. I suspect using a sample chat program wasn't the best start for what I wanted to program...


  6. #6

    Thread Starter
    Addicted Member
    Join Date
    Aug 2002
    Location
    Belfast, N. Ireland
    Posts
    167
    Unfortunately with a little more testing... the problem has not gone away. Things work ok with small amounts of data, but when something a little larger is sent, it is only partially received.



    I'm beginning to get a bit sick looking at this. Does anyone have any other suggestions before I go and buy a book on socket programming????

    Thanks everyone.

  7. #7
    Hyperactive Member
    Join Date
    Dec 2002
    Posts
    382
    Originally posted by Justy
    Unfortunately with a little more testing... the problem has not gone away. Things work ok with small amounts of data, but when something a little larger is sent, it is only partially received.



    I'm beginning to get a bit sick looking at this. Does anyone have any other suggestions before I go and buy a book on socket programming????

    Thanks everyone.

    Hmm, sorry to hear it doesn't work.. I didn't test it with large amounts of data, I honestly think if you're going to be working with alot of data, use asyncronous sockets for your code.. It's alot easier to handle sliced up data over the wire. Give me a bit and I'll whip you something up that should work..

  8. #8
    Hyperactive Member
    Join Date
    Jan 2002
    Location
    Palermo, Italy
    Posts
    325
    VB Code:
    1. While networkStream.DataAvailable
    2.                 networkStream.Read(bytes, 0, CInt(client.ReceiveBufferSize))
    3.                 returndata = returndata & Encoding.ASCII.GetString(bytes)
    4.         End While
    I don't think this is a good way to get data from a stream. You should use the async methods as Hinder said. But if you want to keep this code, try changing it in:
    VB Code:
    1. While networkStream.DataAvailable
    2.                 networkStream.Read(bytes, 0, CInt(client.ReceiveBufferSize))
    3.                 returndata = returndata & Encoding.ASCII.GetString(bytes)
    4.                 Threading.Thread.CurrentThread.Sleep(100) ' Delay of 100ms
    5.         End While
    The problem in fact is that the server sends data slowly and your program gets data really fast. After the beginning chunks of data, your program gets an empty buffer and exits this loop. Try stopping here a little to have a chance to get more data. This is only a workaround and I don't suggest to keep this. Using socket can be a very pain, you must feel sockets...

    Hope this helps.
    Xmas79
    Learn, this is the Keyword...

  9. #9
    Hyperactive Member
    Join Date
    Dec 2002
    Posts
    382
    Ok I just finished this... It works on my end.. It's kinda how I built my server/client for my online game I'm working on.. Few things you gotto do.. first off this is a class.. or you can compile it as a component, doesn't matter whcih way.. just do this in your form....

    Public WithEvents Client As New ClientSocket

    Now on your form you will see the new ClientEvent in the list.. pretty self explanatory..

    You need to set the address of where you want to connect and port..

    Next big thing is you need to figure out what Delimiter the server is using to split the packets up, alot of servers use the CrLf or Chr(0) or Chr(1), it's up to you, but you need to be able to tell where the end of the packet is, so set the EOP value to that and it will work fine.. let me know if it needs anything..


    VB Code:
    1. Imports System
    2. Imports System.Net
    3. Imports System.Net.Sockets
    4. Imports System.Text
    5. Imports System.Threading
    6.  
    7. Public Class SocketState
    8.  
    9. #Region " Declares "
    10.     Public Socket As Socket = Nothing
    11.     Public Const PacketSize As Int32 = 1024
    12.     Public rBuff(PacketSize - 1) As Byte
    13.     Public sBuff() As Byte = Nothing
    14.     Public SB As New StringBuilder
    15. #End Region
    16.  
    17. End Class
    18.  
    19. Public Class ClientSocket
    20.  
    21. #Region " Declares "
    22.     Private Const ServPort As Int32 = 5050
    23.     Private Const ServAddy As String = "localhost"
    24.     Private Const EOP As String = "<EOP>" 'End of Packet
    25.     Private doContinue As New ManualResetEvent(False)
    26.     Private MyState As SocketState = Nothing
    27. #End Region
    28.  
    29. #Region " Events "
    30.     Public Event onReceive(ByVal inMsg As String)
    31.     Public Event onError(ByVal inMsg As String)
    32.     Public Event onFailedConnect(ByVal inMsg As String)
    33.     Public Event onDisconnect(ByVal inMsg As String)
    34.     Public Event onConnect()
    35. #End Region
    36.  
    37. #Region " Methods "
    38.  
    39.     Public Sub New()
    40.         'Default Constructor
    41.     End Sub
    42.  
    43.     Public Sub Start()
    44.         'Start the connection on its own thread
    45.         Dim t As New Thread(AddressOf StartConnect) : t.Start()
    46.     End Sub
    47.  
    48.     Private Sub StartConnect()
    49.  
    50.         'Find the server endpoint
    51.         Dim ipHostEntry As IPHostEntry = Dns.GetHostByName(ServAddy)
    52.         Dim ipAddress As IPAddress = ipHostEntry.AddressList(0)
    53.         Dim ipEndPoint As New IPEndPoint(ipAddress, ServPort)
    54.  
    55.         'Set up the socket
    56.         Dim Connector As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    57.  
    58.         Try
    59.             'Kill the state object just in case
    60.             MyState = Nothing
    61.  
    62.             'Reset the thread pause
    63.             doContinue.Reset()
    64.  
    65.             'Begin trying to connect
    66.             Connector.BeginConnect(ipEndPoint, AddressOf FinishConnect, Connector)
    67.  
    68.             'Pause this thread
    69.             doContinue.WaitOne()
    70.  
    71.         Catch ex As Exception
    72.             RaiseEvent onFailedConnect("A connection to the remote host could not be established.")
    73.         End Try
    74.  
    75.     End Sub
    76.  
    77.     Private Sub FinishConnect(ByVal ar As IAsyncResult)
    78.  
    79.         Dim Handler As Socket = CType(ar.AsyncState, Socket)
    80.  
    81.         Try
    82.  
    83.             If Handler.Connected Then
    84.  
    85.                 'End the connection attempts
    86.                 Handler.EndConnect(ar)
    87.  
    88.                 'Set up the new state
    89.                 MyState = New SocketState
    90.                 MyState.Socket = Handler
    91.  
    92.                 'Begin receiving
    93.                 Handler.BeginReceive(MyState.rBuff, 0, MyState.PacketSize, SocketFlags.None, AddressOf ReceiveLock, MyState)
    94.  
    95.                 'Let the client know we connected
    96.                 RaiseEvent onConnect()
    97.  
    98.             Else
    99.                 CloseSocket()
    100.                 RaiseEvent onFailedConnect("A connection to the remote host could not be established.")
    101.             End If
    102.         Catch
    103.             CloseSocket()
    104.             RaiseEvent onFailedConnect("A connection to the remote host could not be established.")
    105.         Finally
    106.             'Restart the main thread
    107.             doContinue.Set()
    108.         End Try
    109.  
    110.     End Sub
    111.  
    112.     Private Sub ReceiveLock(ByVal ar As IAsyncResult)
    113.  
    114.         Dim State As SocketState = CType(ar.AsyncState, SocketState)
    115.         Dim Handler As Socket = State.Socket
    116.         Dim ByteCount As Int32
    117.  
    118.         Try 'Reteive the data
    119.             ByteCount = Handler.EndReceive(ar)
    120.             If ByteCount > 0 Then
    121.                 State.SB.Append(Encoding.ASCII.GetString(State.rBuff, 0, ByteCount))
    122.                 Dim Msg As String = State.SB.ToString()
    123.                 If Msg.IndexOf(EOP) > -1 Then
    124.                     RaiseEvent onReceive(Msg.Substring(0, Msg.IndexOf(EOP)))
    125.                     State.SB.Remove(0, Msg.IndexOf(EOP) + EOP.Length)
    126.                 End If
    127.                 'Receive more data
    128.                 Handler.BeginReceive(State.rBuff, 0, State.PacketSize, SocketFlags.None, AddressOf ReceiveLock, State)
    129.             Else
    130.                 RaiseEvent onDisconnect("Connection closed by server.")
    131.                 CloseSocket()
    132.             End If
    133.         Catch ex As Exception
    134.             RaiseEvent onError(ex.Message)
    135.             CloseSocket()
    136.         End Try
    137.  
    138.     End Sub
    139.  
    140.     Public Sub SendData(ByVal inMsg As String)
    141.  
    142.         If MyState.Socket.Connected Then
    143.  
    144.             'Package up the message
    145.             MyState.sBuff = Encoding.ASCII.GetBytes(inMsg.Trim)
    146.  
    147.             Try 'Send the message
    148.                 MyState.Socket.BeginSend(MyState.sBuff, 0, MyState.sBuff.Length, SocketFlags.None, AddressOf SendLock, MyState)
    149.             Catch ex As Exception
    150.                 RaiseEvent onError(ex.Message)
    151.             End Try
    152.  
    153.         End If
    154.  
    155.     End Sub
    156.  
    157.     Private Sub SendLock(ByVal ar As IAsyncResult)
    158.  
    159.         'Stop the send request
    160.         Dim State As SocketState = CType(ar.AsyncState, SocketState)
    161.         Dim Handler As Socket = State.Socket
    162.         Dim BytesSent As Int32 = Handler.EndSend(ar)
    163.  
    164.     End Sub
    165.  
    166.     Public Sub CloseSocket()
    167.  
    168.         'Shut down the clients socket
    169.         If (Not MyState Is Nothing) AndAlso (Not MyState.Socket Is Nothing) Then
    170.  
    171.             'Ignore errors
    172.             On Error Resume Next
    173.  
    174.             'Shut it down
    175.             MyState.Socket.Shutdown(SocketShutdown.Both)
    176.             MyState.Socket.Close()
    177.             MyState.Socket = Nothing
    178.  
    179.         End If
    180.  
    181.         'Destroy the state
    182.         MyState = Nothing
    183.  
    184.     End Sub
    185.  
    186. #End Region
    187.  
    188. End Class

  10. #10

    Thread Starter
    Addicted Member
    Join Date
    Aug 2002
    Location
    Belfast, N. Ireland
    Posts
    167
    thanks for your help fellas, especially hinder.. all seems right again


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width