Thank you for explaining that. I'll try your suggested way.
Printable View
Thank you for explaining that. I'll try your suggested way.
Im having some trouble with this code. I am able to send messages from the server to all clients which are displayed in message box's for each. But Im not able to send messages from the client to the server. I am just calling, but the servers message recieved event is never called. Its like its not even getting the message. Also, where in the client code should i call the initial connect message with CONNECT|and the username? -AdamCode:SendMessage("CONNECT|user")
Ah, I believe theres a small misstake in the code. You see, recently I updated the example to make use of message delimiters...altough currently only the server makes use of them. The server will never report that a message is received until a message delimiter is found, and the clients should do the same...let me update the example code, one minute..
Any Luck Fixing the code? -Adam
Try this code on the client side instead:
VB.NET Code:
Public Class Form1 Private client As System.Net.Sockets.TcpClient Private Const MESSAGE_DELIMITER As Char = ControlChars.Cr Private readThread As System.Threading.Thread Private Delegate Sub messageReceivedCallBack(ByVal msg As String) Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load client = New System.Net.Sockets.TcpClient("localhost", 43001) readThread = New System.Threading.Thread(AddressOf doRead) readThread.Start() End Sub Private Sub doRead() Const BYTES_TO_READ As Integer = 255 Dim readBuffer(BYTES_TO_READ) As Byte Dim bytesRead As Integer Dim sBuilder As New System.Text.StringBuilder Do bytesRead = client.GetStream.Read(readBuffer, 0, BYTES_TO_READ) If (bytesRead > 0) Then Dim message As String = System.Text.Encoding.UTF8.GetString(readBuffer, 0, bytesRead) If (message.IndexOf(MESSAGE_DELIMITER) > -1) Then Dim subMessages() As String = message.Split(MESSAGE_DELIMITER) 'The first element in the subMessages string array must be the last part of the current message. 'So we append it to the StringBuilder and raise the dataReceived event sBuilder.Append(subMessages(0)) Me.Invoke(New messageReceivedCallBack(AddressOf messageReceived), sBuilder.ToString()) sBuilder = New System.Text.StringBuilder 'If there are only 2 elements in the array, we know that the second one is an incomplete message, 'though if there are more then two then every element inbetween the first and the last are complete messages: If subMessages.Length = 2 Then sBuilder.Append(subMessages(1)) Else For i As Integer = 1 To subMessages.GetUpperBound(0) - 1 Me.Invoke(New messageReceivedCallBack(AddressOf messageReceived), subMessages(i)) Next sBuilder.Append(subMessages(subMessages.GetUpperBound(0))) End If Else 'MESSAGE_DELIMITER was not found in the message, so we just append everything to the stringbuilder. sBuilder.Append(message) End If End If Loop End Sub Private Sub messageReceived(ByVal message As String) MessageBox.Show(message) End Sub Private Sub SendMessage(ByVal msg As String) Dim sw As IO.StreamWriter Try sw = New IO.StreamWriter(client.GetStream) sw.Write(msg) sw.Flush() Catch ex As Exception MessageBox.Show(ex.ToString) End Try End Sub End Class
Note that you must end each message with ControlChars.Cr (byte value 13).
That may or may not be a good delimiter in your case, if it isnt, just change it to something else.
Atheist,
I have been following this thread for a long while now and have used a great deal of your offerings in the development of a multi client server...
everything works perfectly while in debug mode... (VIA THE IDE)...
how ever once I compile and run as a stand along exe it begins to do weird things, very simular to cross thread talk?
not very sure why or how this occuring as the core of the server is directly from this post..
any thoughts on this issue?
i should note I am not accessing any controls..
Could you describe what you mean by 'weird things'?
it appears that more than not, the server doesn't read the streams from the cleints...
but only when it's a stand alone exe... when I run it from the IDE I can connect 500 clients and it performs flawlessly?
OK, Much better, its working good now, All I am having trouble with now is adding the users to a list box but the username they sent. I can add the username, but im not sure how to designate it to the specific client that it came from, so basically all im getting is a list box with a list of usernames that do nothing. -Adam
oddly enough though if I make the thread sleep for 1 ms during the read loop.... things work properly in both the IDE and the compiled exe.
vb Code:
If (bytesRead > 0) Then System.Threading.Thread.Sleep(1)
this in the connectedClient class doRead sub resolves the issue I'm describing..
though my question is, is this the proper way to do this??
or am i looking at a larger problem?
I finally got your code to work :), but I'm having trouble connecting to the server through the internet. I set my router to forward the port 43001 to my computer that has the server running. The server program is unblocked on the Vista computer, but it still fails. Visual Studio says (this is the ClientChat program):
I don't know what to do, and I'd really like it to work over the internet.Code:System.Net.Sockets.SocketException was caught
ErrorCode=10061
Message="No connection could be made because the target machine actively refused it (IP Address):43001"
NativeErrorCode=10061
Source="System"
StackTrace:
at System.Net.Sockets.TcpClient..ctor(String hostname, Int32 port) at ClientChat.MainForm.Connect() in C:\Users\(User Name)\Documents\Visual Studio 2008\Projects\ServerChat\ClientChat\MainForm.vb:line 275
InnerException:
That only happens if
A) The server is not running.
B) The server IS running but the port hasnt been forwarded correctly.
C) The server is blocked in the software firewall.
Go into your router settings and double-check, have you forwarded the port to the correct local IP?
I use the Actiontec MI424WR for Verizon Fios.
Windows Firewall is configured to allow ServerChat to open any ports.
Here's the setup pictures from the router.
http://digitalcircuit36939.googlepages.com/Port1.PNG
http://digitalcircuit36939.googlepages.com/Port2.PNG
http://digitalcircuit36939.googlepages.com/Port3.PNG
And you're 100% sure that the computer running the server has that local IP? 192.168.1.2.
Yes. I opened the Windows Network Map, and it listed that computer's local IP address as 192.168.1.2
It should be noted that verizon fios blocks a huge list of inbound ports for non commercial accounts...
You may want to test with other previously tested software in conjunction with proper port forwarding techniques to determine if a connection is possible in the first place.
hello. I have been searching google, msdn and every vb forum on the net for 6 days now looking for an easy example of sending a simple text string from one computer(client) to another(server).
Everything is very advanced and does not cover the basics or does not work. So your example is my last try before i go back to winsock.
I have more or less accomplished to receive a text string with your example but i have a question.
How can i use this part of the code. It seems like it is not used, but it seems to have a function.
Is it something wrong i have dont ?
Private Sub messageReceived(ByVal sender As ConnectedClient, ByVal message As String)
'A message has been received from one of the clients.
'To determine who its from, use the sender object.
'sender.SendMessage can be used to reply to the sender.
Dim data() As String = message.Split("|"c) 'Split the message on each | and place in the string array.
Select Case data(0)
Case "CONNECT"
'We use GetClientByName to make sure no one else is using this username.
'It will return Nothing if the username is free.
'Since the client sent the message in this format: CONNECT|UserName, the username will be in the array on index 1.
If GetClientByName(data(1)) Is Nothing Then
'The username is not taken, we can safely assign it to the sender.
sender.Username = data(1)
End If
Case "DISCONNECT"
removeClient(sender)
End Select
End Sub
Please help me.
Welcome to the forums.
That method is the DataReceived event handler, each time a new client connects to the server, this handler is automatically added to its DataReceived event.
Every time a full message (message + delimiter) has been received, this method is invoked and the message is passed as a parameter.
I am having trouble trying to send a file from the server to the client. At the moment i am reading a file into a byte array, converting it to string then sending it to the client. When the client receives the string, it converts it back to a byte array and writes it to a file. However, when i tryed this using a jpg image, the image that the client received seemed to have all the colors messed up. I opened up both images in notepad to compare them and saw that certain characters in the newly created file were replaced by a "??". Also, i noticed that the length of the string received was a few 100 characters more than the length of the string sent. The code that i am currently using is below. Is anybody able to help me identify what the problem is.
Server:
Client:Code:Dim a() As Byte = My.Computer.FileSystem.ReadAllBytes("C:\image.jpg")
Dim b As String = System.Text.Encoding.Default.GetString(a)
For Each cc As ConnectedClient In clients
cc.SendMessage(b + MESSAGE_DELIMITER)
Next
Code:Dim c() As Char = message.ToCharArray
Dim d() As Byte = System.Text.Encoding.Default.GetBytes(c)
My.Computer.FileSystem.WriteAllBytes("C:\image2.jpg", d, False)
You shouldnt convert the byte arrays to strings before sending, you're going to loose byte values. It is going to get complicated if you want to send files on the same connection as you send other messages, but if you really must do it:
Create a modified SendMessage function that takes a byte array as input and sends it, name it something neat such as SendData.
Use this SendData method to send the file data instead of SendMessage.
Thank you for your reply. I have tried creating a SendData function as you suggested. However, the client doesn't seem to show that a message has been received. Below is the SendData function and the code i am using to send the data. I also tried to add the Message Delimiter to the end of the byte array as i thought that it could be causing the problem but it hasn't helped. Would I have to change the code on the client side to be able to receive the byte array.
SendData function:
Server code:Code:Public Sub SendData(ByVal bytes As Byte())
Dim sw As IO.StreamWriter
Try
SyncLock mClient.GetStream
sw = New IO.StreamWriter(mClient.GetStream) 'Create a new streamwriter that will be writing directly to the networkstream.
sw.Write(bytes)
sw.Flush()
End SyncLock
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
'As opposed to writing to a file, we DONT call close on the streamwriter, since we dont want to close the stream.
End Sub
Code:Dim a() As Byte = My.Computer.FileSystem.ReadAllBytes("C:\image.jpg")
Array.Resize(a, a.Length + 1)
a(a.Length - 1) = 13 'This is the byte value of the MESSAGE_DELIMITER
For Each cc As ConnectedClient In clients
cc.SendData(a)
Next
How does your datareceived eventhandler look?
This is one of the major drawbacks of sending files on the same connection as other data, if the value of the message delimiter is contained anywhere within the file data (which is very likely), it simply wont work as it should.
I've provided examples for file transfers in this thread, that uses a separate connection for each file.
I haven't created a datareceived event handler because i am quite new to vb and not sure how to. At the moment, the code on the client side is exactly the same as your example on the first page but has the code in my previous post in the messagereceived sub. So it looks like:
I have read the examples for file transfers on the thread you mentioned and am wondering if I would be able to add the FileTransferSend class to the server and the FileTransferReceive class to the client. Could I send a message from the client to the server requesting it to start the FileTransferSend and then start the FileTransferReceive for the client. I am assuming the file transfer classes would have to use a different port to connect.Code:Private Sub messageReceived(ByVal message As String)
Dim c() As Char = message.ToCharArray
Dim d() As Byte = System.Text.Encoding.Default.GetBytes(c)
My.Computer.FileSystem.WriteAllBytes("C:\image.jpg", d, False)
End Sub
EDIT: I managed to get it working using your example on the thread you suggested. It works perfectly. Thank you for all your help.
Hello,jk108 i had the same question for Atheist. I want to send a file from the client to the server, i was wondering if you can give some tips of how you do it or upload your project to gimme some directions.
Thanks in advance
I was able to send a file from the server to the client providing the correct port was forwarded on the servers side but I am still having trouble sending something from the client to the server because it would require the client to forward the port on their router which isn't really ideal. On the thread with the file transfer classes, the receiving end connects to the sending end. I can't figure out how to make it do it the other way round. I remember using an old version of the client and server in this thread before message delimiters were used and i was able to successfully transfer files by converting them to a string, sending that string and then converting it back to a file on the other end. But unfortunately my computer completely died on me including the hdd's and I hadn't backed it up. I've tried using the latest version of the client and server by replacing all instances of the message delimiter in the string and then doing the opposite at the other end before writing it to a file but for some reason it gave me strange files. It looked something like this:
Client:
Server:Code:Dim a() As Byte = My.Computer.FileSystem.ReadAllBytes("C:\image.jpg")
Dim b As String = System.Text.Encoding.Default.GetString(a)
b = b.Replace(MESSAGE_DELIMITER, "|?|:|")
SendMessage(b + MESSAGE_DELIMITER)
Code:message = message.Replace("|?|:|", MESSAGE_DELIMITER)
Dim c() As Char = message.ToCharArray
Dim d() As Byte = System.Text.Encoding.Default.GetBytes(c)
My.Computer.FileSystem.WriteAllBytes("C:\image2.jpg", d, False)
question,
i want to try to show a new form whenever my client received a message
but when i add this to
vb Code:
private void messageReceived(string mssg){ MessageBox.Show(mssg); frmPrivate frmPrivate = new frmPrivate(); frmPrivate.Show(); }
the frmPrivate hangs up then closes
Thats because the messageReceived eventhandler is raised on a worker thread. You'll have to create a new method, put the code to open 'frmPrivate' in there, and invoke that method using, for instance, this.Invoke.
this is what i did
frmPrivate frmPrivate = new frmPrivate(client,messageDetails[3]);
if(this.InvokeRequired) {
this.Invoke(
(MethodInvoker) delegate() {
frmPrivate.Show(this);
ListOfOpenWindows.Add(frmPrivate);
}
);
}
and it worked...
..this is a good example.. could some one build a project on this ?
Well this is C# or C++ code so try posting it on a forum that is specifically designed for those languages.
hello Atheist, (i am new on socket programming)
when i using the code that provide from perito http://www.vbforums.com/showpost.php...2&postcount=14
i create 1 form and 1 class ... ( for server and clientconnect)
another one which is client (from) (i run it on 2 Microsoft visual studio - 1 for server and another for client)
when i run server and client , it didn't show anything ... is it anything worng ?
Hello.
Your link isnt working so I cant see what code example you're referring to.
What are you expecting to happen when you run the two applications?
sorry the link got mistake ... is this http://www.vbforums.com/showpost.php...2&postcount=14
Yeah I could do that, I'm a bit busy this week but I can throw something together next week.
Ah yes okay.
What is not happening, that you expect to happen, when you run that code?
If you start the server side first, then the client, the client will attempt to connect to the server. It does not do anything more than that.
I'm using the sample code posted by Atheist for connection between server and client, however i wanna disable client task manager by clicking certain button in server.....any idea?
Welcome to VBForums.
This question doesnt have anything to do with the subject, as it doesnt really touch networking at all. You'd have to create a new thread on the subject of disabling the taskmanager, which is generally seen as a malicious thing, so you might want to (in your new thread) explain exactly for what purpose you need to disable the taskmanager.
Thanks for welcome me, i'm new to here...
Currently, i'm developing an application like internet cafe system in visual basic .net 2008 and i'm wondering if the previous posted code could help me in this development? Moreover, this is my first time for developing this kind of software
Well, the code in this thread will just give you a foundation to develop a client/server application. So if you need to be able to communicate with the computers in the "internet cafe" then you have some of the code to help you do so. However that would be just one small piece in building that kind of software. Disabling task managers and all that other non-networking stuff is another story.