Question Client/Server formatted text sending/receiving??

anubhavmax

Member
Joined
Jan 21, 2009
Messages
10
Programming Experience
Beginner
I have been wrting a code to develop an Instant messenger by modifying an open source code project available at
Home-brew Your Own Instant Messenger App with Visual Studio .NET

Instead of the send message text box and message display text box, I have replaced it with RichTextBox for text formatting (bold/italics/underline/font/color). The problem I am facing is when I format the text and click on send, then the text displayed on the message display box (txtMessageHistory) is unformatted.

Here is the code for server--

VB.NET:
Public Class ChatClient
    '---contains a list of all the clients
    Public Shared AllClients As New HashTable

    '---information about the client
    Private _client As TcpClient
    Private _clientIP As String
    Private _ClientNick As String

    '---used for sending/receiving data
    Private data() As Byte

    '---is the nick name being sent?
    Private ReceiveNick As Boolean = True

Public Sub New(ByVal client As TcpClient)
        _client = client

        '---get the client IP address
        _clientIP = client.Client.RemoteEndPoint.ToString

        '---add the current client to the hash table
        AllClients.Add(_clientIP, Me)

        '---start reading data from the client in a 
        '   separate thread
        ReDim data(_client.ReceiveBufferSize)
        _client.GetStream.BeginRead(data, 0, _
           CInt(_client.ReceiveBufferSize), _
           AddressOf ReceiveMessage, Nothing)
    End Sub

  <b>Public Sub ReceiveMessage(ByVal ar As IAsyncResult)
        '---read from client---
        Dim bytesRead As Integer
        Try
            SyncLock _client.GetStream
                bytesRead = _client.GetStream.EndRead(ar)
            End SyncLock
            '---client has disconnected
            If bytesRead < 1 Then
                AllClients.Remove(_clientIP)
                Broadcast(_ClientNick & _
                              " has left the  chat.")
                Exit Sub
            Else
                '---get the message sent
                Dim messageReceived As String = _
                    System.Text.Encoding.ASCII. _
                    GetString(data, 0, bytesRead)
                '---client is sending its nickname
                If ReceiveNick Then
                    _ClientNick = messageReceived

                    '---tell everyone client has entered 
                    '   the chat
                    Broadcast(_ClientNick & _
                       " has joined the chat.")
                    ReceiveNick = False
                Else
                    '---broadcast the message to everyone
                    Broadcast(_ClientNick & ">" & _
                       messageReceived)
                End If
            End If
            '---continue reading from client
            SyncLock _client.GetStream
                _client.GetStream.BeginRead(data, 0, _
                   CInt(_client.ReceiveBufferSize), _
                   AddressOf ReceiveMessage, Nothing)
            End SyncLock

        Catch ex As Exception
            AllClients.Remove(_clientIP)
            Broadcast(_ClientNick & _
               " has left the chat.")
        End Try
    End Sub</b>

Public Sub SendMessage(ByVal message As String)
        Try
            '---send the text
            Dim ns As System.Net.Sockets.NetworkStream
            SyncLock _client.GetStream
                ns = _client.GetStream
            End SyncLock
            Dim bytesToSend As Byte() = _
             System.Text.Encoding.ASCII.GetBytes(message)
            ns.Write(bytesToSend, 0, bytesToSend.Length)
            ns.Flush()
        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        End Try
    End Sub
Finally, the Broadcast() function sends a message to all the clients stored in the AllClients HashTable object. 

    Public Sub Broadcast(ByVal message As String)
        '---log it locally
        Console.WriteLine(message)
        Dim c As DictionaryEntry
        For Each c In AllClients
            '---broadcast message to all users
            CType(c.Value, _
               ChatClient).SendMessage(message & vbCrLf)
        Next
    End Sub

The problem here is whenever the server sends or receives a message from the client, it receives it in the form of a string that has no formatting in it.

here is the code for the client-
VB.NET:
Public Sub SendMessage(ByVal message As String)
        Try
            '---Send A Message To The Server
            Dim ns As NetworkStream = client.GetStream
            Dim data As Byte() = _
            System.Text.Encoding.ASCII.GetBytes(message)
            '---Send The Text
            ns.Write(data, 0, data.Length)
            ns.Flush()
        Catch ex As Exception
            MsgBox("Server Disconnected")
            'MsgBox(ex.ToString)
        End Try
    End Sub

    Public Sub ReceiveMessage(ByVal ar As IAsyncResult)
        Try
            Dim bytesRead As Integer
            bytesRead = client.GetStream.EndRead(ar)
            If bytesRead < 1 Then
                Exit Sub
            Else
                Dim para() As Object = _
                   {System.Text.Encoding.ASCII.GetString( _
                   data, 0, bytesRead)}
                Me.Invoke(New delUpdateHistory( _
                   AddressOf Me.UpdateHistory), para)
            End If
            client.GetStream.BeginRead( _
               data, 0, CInt(client.ReceiveBufferSize), _
               AddressOf ReceiveMessage, Nothing)
        Catch ex As Exception
        End Try
    End Sub


Private Sub btnSignIn_Click( _
       ByVal sender As System.Object, _
       ByVal e As System.EventArgs) _
       Handles btnSignIn.Click
        If btnSignIn.Text = "Sign In" Then
            Try
                '---Connect To The Server
                client = New TcpClient
                client.Connect(TextBox1.Text, portNo)
                ReDim data(client.ReceiveBufferSize)
                SendMessage(txtNick.Text)
                MsgBox("Successfully logged in")
                '---Read From The Server
                client.GetStream.BeginRead( _
                   data, 0, CInt(client.ReceiveBufferSize), _
                   AddressOf ReceiveMessage, Nothing)
                btnSignIn.Text = "Sign Out"
                btnSend.Enabled = True
            Catch ex As Exception
                MsgBox("Server is not reachable")

            End Try
        Else
            '---Disconnect From The Server By Signing Out From The Client
            Disconnect()
            MsgBox("Successfully logged off")
            btnSignIn.Text = "Sign In"
            btnSend.Enabled = False
        End If
    End Sub

    Public Sub Disconnect()
        '---Disconnect From The Server By Closing The Client
        Try
            client.GetStream.Close()
            client.Close()
        Catch ex As Exception
            'MessageBox.Show("Session Closed ")
        End Try
    End Sub

    '---Delegate And Subroutine To Update The TextBox Control
    Public Delegate Sub delUpdateHistory(ByVal str As String)
    Public Sub UpdateHistory(ByVal str As String)
        txtMessageHistory.AppendText(Str)
    End Sub
    '--- Disconnect() method to Disconnect The Client From The Server And Close The Client 
    Private Sub Form1_FormClosing( _
       ByVal sender As Object, _
       ByVal e As System.Windows.Forms.FormClosingEventArgs) _
       Handles Me.FormClosing
        Disconnect()
    End Sub

Rest of the code of client is related to formatting of the rich text boxes that is not relevant to my problem.

I just need to transfer the formatted text from clint to server and then back to the client the same way and display the message with text formatting. Any kind of help would relly be appreciated.
 
Last edited by a moderator:
The purpose of the "science projects" is to test a small part of program with least effort. You don't need any server or client programs or any sockets and connections to run this code and figure out the logic. Forget your applications and run the sample codes till you see how things work. After that you can add the same code logic to the server and client apps.

I went thru the thread again
1) The sender side should inform the receiving side about the size of
Yes, if you are sending information in chunks of bytes, then that is what you must do. If you instead use reader/writer then all is taken care of as I have explained, all you need then is one write call in sender and one read call in receiver. I will again suggest you take this route for starters, you could always drown yourself in bytes management later when you are more experienced.
 
Well..fine...Can you jst try out to give a working code for my problem. I had executed the science project and that worked...and came to know all this....but please..I request you to edit the source file so that it works out. Atleast after viewing the solution , I would be able to understand where I was wrong. I had been working for this since last 2 weeks and now I am stuck up with this problem. I need to get it done till JaN 28th. Since you r a real expert , please help me out and give the solution.
 
I have already given you working code, see post 12. This is also the same code I gave you in post 4. A Stream is a Stream, there is no difference between using a MemoryStream as in that sample, and using a NetworkStream like sockets use, as you can see in code sample of post 4.
 
but in post 13 as you can see...I used the code..but still I am unbale to receive the output.
What is the mistake that I hav made in updated code written in post 13
 
Your BeginRead calls ruin the day basically, so you have to remove all of them.

Here is example of variables that can be used:
VB.NET:
Private client As Net.Sockets.TcpClient
Private writer As IO.BinaryWriter
Private reader As IO.BinaryReader
Here is example of initializing them:
VB.NET:
client = New Net.Sockets.TcpClient("host", 12345)
reader = New IO.BinaryReader(client.GetStream)
writer = New IO.BinaryWriter(client.GetStream)
Here is an example of how you can start a loop in a thread to check for messages:
VB.NET:
Threading.ThreadPool.QueueUserWorkItem(AddressOf receiver)
Here is an example of such a receiver method:
VB.NET:
Private Sub receiver()
    Do
        If client.GetStream.DataAvailable Then
            Dim message As String = reader.ReadString
            'do what you want with message
        End If
        Threading.Thread.Sleep(500)
    Loop
End Sub
 
Back
Top