|
-
Sep 23rd, 2009, 10:24 PM
#1
Thread Starter
Stack Overflow moderator
How to stop connection rejection
I get an error saying that the connection was rejected by the target machine here, suggesting that my firewall is working well 
How do I make sure that the connection is accepted? It's a chat program (obviously) so I'm going to need to do the same thing on users' computers when it is installed. How do I make this in such a way that the connection will be accepted but leaving security uncomprimised?
vb.net Code:
Imports System.Net.Sockets
Public Class QuickChat
'Dim invited As List(Of String) = New List(Of String) 'ip addresses
Dim ip(3) As Byte
Dim conn As NetworkStream
'Dim s As Socket
Dim tcpclient As TcpClient
'Dim tcplistener As TcpListener
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Set up form
Dim si As Size = Screen.GetWorkingArea(New Point(1, 1)).Size
Me.MaximumSize = New Size(si.Width \ 3, si.Height)
Me.Width = Me.MaximumSize.Width
'Retrieve chat IP.
Dim ipre As New System.Text.RegularExpressions.Regex("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
Dim cip As String = InputBox("Please enter the IP address of the person that you would like to send to.", "Enter IP Address", "0.0.0.0")
If Not ipre.IsMatch(cip) Then
Me.Close()
Exit Sub
End If
Dim ipbs() As String = cip.Split(".")
ip(0) = CByte(ipbs(0))
ip(1) = CByte(ipbs(1))
ip(2) = CByte(ipbs(2))
ip(3) = CByte(ipbs(3))
'Set up send/recieve
tcpclient = New TcpClient()
tcpclient.Connect(New Net.IPAddress(ip), 120)
conn = tcpclient.GetStream()
Me.tmrCheckForMessage.Start()
End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
SendMsg(Me.txtNewMessage.Text)
End Sub
Private Sub SendMsg(ByVal msg As String)
Dim c As Char
For Each c In msg
conn.WriteByte(AscW(c))
Next
conn.WriteByte(0)
End Sub
Private Function GetMsgIfAny() As String
Dim b As Byte = conn.ReadByte()
Dim str As String = ""
While b > 0
str &= ChrW(b)
b = conn.ReadByte()
End While
Return str
End Function
Private Sub tmrCheckForMessage_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrCheckForMessage.Tick
Dim s As String = GetMsgIfAny()
If s = "" Then Exit Sub
Me.txtChatLog.Text &= String.Format("{0}{1}{0}{0}", ControlChars.CrLf, s)
End Sub
End Class
-
Sep 23rd, 2009, 10:30 PM
#2
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
oh my gosh, I'm an idiot...
use the TCP port 445 and it works.
But don't worry, there's still a problem... 
The ReadByte() call freezes the app if there's no data coming in, even though it's running on a different thread. (Same thing with SerialPorts.) Why is this, and how do I fix it?
-
Sep 23rd, 2009, 10:55 PM
#3
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
Ok, I looked it up online and I used the TcpListener object instead. Now, on line 15, it says "you have attempted to access a socket in a way forbidden by its access permissions." WHY??? 
vb.net Code:
Imports System.Net.Sockets
Public Class Form1
Dim currentstr() As Byte
'Dim invited As List(Of String) = New List(Of String) 'ip addresses
Dim ip(3) As Byte
Dim conn As NetworkStream
'Dim s As Socket
Dim tcpclient As TcpClient
Dim tcplistener As TcpListener
Dim listenert As Threading.Thread = New Threading.Thread(AddressOf TcpListen)
Dim isclosing As Boolean = False
Delegate Sub NCDeleg(ByVal txtadd As String)
Dim ncinvoke As NCDeleg = New NCDeleg(AddressOf NotifyConn)
Private Sub TcpListen()
[B]tcplistener.Start()[/B]
While Not isclosing
If tcplistener.Pending() Then
Dim rs As NetworkStream = tcplistener.AcceptTcpClient().GetStream()
Dim b As Byte = rs.ReadByte
Dim str As String = ""
While b > 0
str &= ChrW(b)
b = rs.ReadByte()
End While
Me.Invoke(ncinvoke, str)
End If
Threading.Thread.Sleep(500)
End While
tcplistener.Stop()
End Sub
Private Sub NotifyConn(ByVal txtadd As String)
Me.txtChatLog.Text &= String.Format("{0}{1}{0}{0}", ControlChars.CrLf, txtadd)
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
isclosing = True
listenert.Join()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Set up form
Dim si As Size = Screen.GetWorkingArea(New Point(1, 1)).Size
Me.MaximumSize = New Size(si.Width \ 3, si.Height)
Me.Width = Me.MaximumSize.Width
'Retrieve chat IP.
Dim ipre As New System.Text.RegularExpressions.Regex("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
Dim cip As String = InputBox("Please enter the IP address of the person that you would like to send to.", "Enter IP Address", "0.0.0.0")
If Not ipre.IsMatch(cip) Then
Me.Close()
Exit Sub
End If
Dim ipbs() As String = cip.Split(".")
ip(0) = CByte(ipbs(0))
ip(1) = CByte(ipbs(1))
ip(2) = CByte(ipbs(2))
ip(3) = CByte(ipbs(3))
''Set up sockets
's = New Socket(AddressFamily.DataLink, SocketType.Stream, ProtocolType.Tcp)
's.Connect(New Net.IPAddress(ip), 120)
'conn = New NetworkStream(s, IO.FileAccess.ReadWrite, True)
tcpclient = New TcpClient()
Try
tcpclient.Connect(New Net.IPAddress(ip), 445)
Catch ex As SocketException
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Me.Close()
Exit Sub
End Try
'tcplistener = New TcpListener(New Net.IPAddress(ip), 120)
conn = tcpclient.GetStream()
'conn.ReadTimeout = 10
tcplistener = New TcpListener(New Net.IPAddress(ip), 445)
listenert.Start()
'Me.tmrCheckForMessage.Start()
End Sub
'Private Sub btnInvite_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInvite.Click
' Dim ip As New System.Text.RegularExpressions.Regex("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
' Dim val As String = InputBox("Please enter the IP address of the person that you would like to send to.", "Enter IP Address", "0.0.0.0")
' If Not ip.IsMatch(val) Then
' If val = "" Then Exit Sub
' MessageBox.Show("Invalid IP address.", "Invalid IP", MessageBoxButtons.OK, MessageBoxIcon.Error)
' Exit Sub
' End If
' invited.Add(val)
'End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
SendMsg(Me.txtNewMessage.Text)
Me.txtNewMessage.Text = ""
End Sub
Private Sub SendMsg(ByVal msg As String)
Dim c As Char
For Each c In msg
conn.WriteByte(AscW(c))
Next
conn.WriteByte(0)
End Sub
' Private Function GetMsgIfAny() As String
' On Error GoTo sub_exit
' Dim b As Byte = conn.ReadByte()
' Dim str As String = ""
' While b > 0
' str &= ChrW(b)
' b = conn.ReadByte()
' End While
' Return str
'sub_exit:
' GetMsgIfAny = ""
' End Function
'Private Sub GetAsyncMsg(ByVal ia As IAsyncResult)
' If ia.IsCompleted Then
' End If
'End Sub
'Private Sub tmrCheckForMessage_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrCheckForMessage.Tick
' Dim s As String = GetMsgIfAny()
' If s = "" Then Exit Sub
' Me.txtChatLog.Text &= String.Format("{0}{1}{0}{0}", ControlChars.CrLf, s)
' conn.BeginRead(currentstr, 0, 1, AddressOf GetAsyncMsg, Nothing)
'End Sub
End Class
-
Sep 23rd, 2009, 11:09 PM
#4
Re: How to stop connection rejection
You say:
even though it's running on a different thread
but I see no sign of multiple threads there. The Timer.Tick event is raised on the UI thread so your tmrCheckForMessage_Tick event handler is executed on the UI thread. That's where you call GetMsgIfAny, so that's executed on the UI thread too, and that's where you call ReadByte, so that's executed on the UI thread too.
The NetworkStream class already provides asynchronous methods so, if you want to read the data asynchronously, that's what you should use. You simply call BeginRead and pass a callback and then let it go. Your callback will be invoked when data becomes available so you read it there.
-
Sep 23rd, 2009, 11:15 PM
#5
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
I just added the extra thread. I can't use BeginRead because I don't know how many bytes I need to read.
-
Sep 23rd, 2009, 11:17 PM
#6
Re: How to stop connection rejection
 Originally Posted by minitech
I just added the extra thread. I can't use BeginRead because I don't know how many bytes I need to read.
I don't see why that would be an impediment to using BeginRead. Most people don't know how many bytes they need to read. You just keep reading until there are no bytes left to read, pretty much as you're doing now but you would Read in blocks instead of one byte at a time with ReadByte.
-
Sep 23rd, 2009, 11:26 PM
#7
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
How do you do that? BeginRead asks for the number of bytes to read. Does it automatically stop reading if there are no more?
-
Sep 23rd, 2009, 11:32 PM
#8
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
Ok, I've got it like this, but the message box never shows up.
vb Code:
Private Sub GetAsyncMsg(ByVal ia As IAsyncResult)
MessageBox.Show("Data recieved!!")
conn.BeginRead(currentstr, 0, currentstr.Length, AddressOf GetAsyncMsg, Nothing)
End Sub
-
Sep 23rd, 2009, 11:39 PM
#9
Re: How to stop connection rejection
 Originally Posted by minitech
How do you do that? BeginRead asks for the number of bytes to read. Does it automatically stop reading if there are no more?
Just pick a good size for a buffer, e.g. 1024, and read blocks of that size. You call BeginRead and let it go. Your callback will be invoked and you'll read a block of data up to the size specified. If the actual amount of data read is less than that you know that that's all the data there was to read. If the actual amount read is equal to the size of the buffer then either that's the exact amount of data there was or there's more to read, which you can determine from the DataAvailable property. Once you've read a block you simply call BeginRead again and your callback will be invoked again, either immediately if there is more data t read or else later, when more data becomes available.
You might want to check out the documentation for the EndRead method for a simple example that you can then build on.
-
Sep 23rd, 2009, 11:48 PM
#10
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
Nothing doing, still not working. 
Is it something to do with the fact that I'm using the same connection for read/write and that the IP address that I entered is my own?
-
Sep 24th, 2009, 01:00 AM
#11
Re: How to stop connection rejection
As is always the case, when you're having trouble with one aspect of a project you should forget about the project for the time being. You should create a brand new project and test ONLY the functionality that you're having trouble with. By removing all other distractions you are able to concentrate on just that functionality and getting it to work. Once you've got it working, then you can worry about integrating it back into your original project.
With that in mind, you should have done something like what I did:
1. Create a new WinForms project.
2. Add three Buttons to the form.
3. Add the following code:
Code:
Imports System.Net.Sockets
Imports System.Net
Imports System.IO
Imports System.Text
Public Class Form1
Private listener As New TcpListener(IPAddress.Parse("127.0.0.1"), 1234)
Private server As TcpClient
Private client As TcpClient
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.listener.Start()
Me.listener.BeginAcceptTcpClient(AddressOf AcceptTcpClient, Me.listener)
End Sub
Private Sub AcceptTcpClient(ByVal ar As IAsyncResult)
Me.server = Me.listener.EndAcceptTcpClient(ar)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.client = New TcpClient()
Me.client.Connect("127.0.0.1", 1234)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim buffer As Byte() = Encoding.ASCII.GetBytes(InputBox("Enter the message to send:", "Send"))
Me.client.GetStream().Write(buffer, 0, buffer.Length)
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim stream As NetworkStream = Me.server.GetStream()
Dim buffer(16 - 1) As Byte
stream.BeginRead(buffer, _
0, _
buffer.Length, _
AddressOf Read, _
New Object() {stream, _
buffer})
End Sub
Private Sub Read(ByVal ar As IAsyncResult)
Dim userState As Object() = DirectCast(ar.AsyncState, Object())
Dim stream As NetworkStream = DirectCast(userState(0), NetworkStream)
Dim bytesRead As Integer = stream.EndRead(ar)
Dim buffer As Byte() = DirectCast(userState(1), Byte())
Static message As String
message &= Encoding.ASCII.GetString(buffer, 0, bytesRead)
If bytesRead = buffer.Length AndAlso stream.DataAvailable Then
stream.BeginRead(buffer, _
0, _
buffer.Length, _
AddressOf Read, _
New Object() {stream, _
buffer})
Else
MessageBox.Show(message, "Receive")
message = Nothing
End If
End Sub
End Class
4. Run the project.
5. Click Button1 to make the connection.
6. Click Button2 and enter the message to send.
7. Click Button3 to read the message received.
You'll see that, even though only 16 bytes are being read at a time, the entire message is received and displayed, no matter how long it is.
Last edited by jmcilhinney; Sep 24th, 2009 at 01:05 AM.
-
Sep 25th, 2009, 06:36 PM
#12
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
Ok. It works. But when I put it into my code, on the line that says "tcplistener.Start()", it says that it was accessed in a way forbidden by its access permissions. It's in Form_Load, just like your example. I tried it out with my IP and 127.0.0.1. Nothing works.
-
Sep 25th, 2009, 06:45 PM
#13
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
I took out the tmrCheckForMessages.Start() line, and it started working. There was nothing in its event handler. Why did it start working all of a sudden like that?
There's only one more problem. It prints the first character, then the rest of the message. Why does that happen?
vb.net Code:
Imports System.Net.Sockets
Public Class Form1
Dim currentstr(0) As Byte
Dim conn As NetworkStream
Dim tcpclient As TcpClient
Dim tcprecieve As TcpClient
Dim tcplistener As TcpListener
Dim inconn As NetworkStream
Delegate Sub NotifyDeleg(ByVal txt As String)
Dim ndinvoke As NotifyDeleg = New NotifyDeleg(AddressOf NotifyConn)
Private Sub NotifyConn(ByVal txtadd As String)
Me.txtChatLog.Text &= String.Format("{0}Chatter said:{0}{0}{1}{0}{0}", ControlChars.CrLf, txtadd)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Set up form
Dim si As Size = Screen.GetWorkingArea(New Point(1, 1)).Size
Me.MaximumSize = New Size(si.Width \ 3, si.Height)
Me.Width = Me.MaximumSize.Width
'Retrieve chat IP.
Dim ipre As New System.Text.RegularExpressions.Regex("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
Dim cip As String = InputBox("Please enter the IP address of the person that you would like to send to.", "Enter IP Address", "0.0.0.0")
If Not ipre.IsMatch(cip) Then
Me.Close()
Exit Sub
End If
Me.txtChatLog.Text = "Begin chat with computer " & cip & ControlChars.CrLf
tcpclient = New TcpClient()
tcplistener = New TcpListener(Net.IPAddress.Parse(cip), 1234)
tcplistener.Start()
tcplistener.BeginAcceptTcpClient(AddressOf AcceptTcpClient, Nothing)
Try
tcpclient.Connect(Net.IPAddress.Parse(cip), 1234)
conn = tcpclient.GetStream()
Catch ex As SocketException
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Me.Close()
Exit Sub
End Try
End Sub
#Region "Callbacks"
Private Sub AcceptTcpClient(ByVal ia As IAsyncResult)
tcprecieve = tcplistener.EndAcceptTcpClient(ia)
inconn = tcprecieve.GetStream()
Dim buf(1023) As Byte
inconn.BeginRead(buf, 0, buf.Length - 1, AddressOf AcceptData, buf)
End Sub
Private Sub AcceptData(ByVal ia As IAsyncResult)
Dim buf() As Byte = DirectCast(ia.AsyncState, Byte())
Dim str As String = System.Text.Encoding.ASCII.GetString(buf)
Me.Invoke(ndinvoke, str)
inconn.BeginRead(buf, 0, buf.Length - 1, AddressOf AcceptData, buf)
End Sub
#End Region
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
SendMsg(Me.txtNewMessage.Text)
Me.txtNewMessage.Text = ""
End Sub
Private Sub SendMsg(ByVal msg As String)
Try
Dim c As Char
For Each c In msg
conn.WriteByte(AscW(c))
Next
Me.txtChatLog.Text &= String.Format("{0}You said:{0}{0}{1}{0}{0}", ControlChars.CrLf, msg)
Catch ex As SocketException
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Me.Close()
Exit Sub
End Try
End Sub
End Class
-
Sep 25th, 2009, 08:46 PM
#14
Re: How to stop connection rejection
I'll start of with a suggestion coding style. I look at that big chunk of code you posted and I find it very hard to read. I tend to use lots of blank lines in my code to separate logical chunks of code and, in my opinion, it makes the code much easier to look at. I would suggest that you, and anyone else, do the same, e.g.
vb.net Code:
Imports System.Net.Sockets Public Class Form1 Dim currentstr(0) As Byte Dim conn As NetworkStream Dim tcpclient As TcpClient Dim tcprecieve As TcpClient Dim tcplistener As TcpListener Dim inconn As NetworkStream Delegate Sub NotifyDeleg(ByVal txt As String) Dim ndinvoke As NotifyDeleg = New NotifyDeleg(AddressOf NotifyConn) Private Sub NotifyConn(ByVal txtadd As String) Me.txtChatLog.Text &= String.Format("{0}Chatter said:{0}{0}{1}{0}{0}", ControlChars.CrLf, txtadd) End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Set up form Dim si As Size = Screen.GetWorkingArea(New Point(1, 1)).Size Me.MaximumSize = New Size(si.Width \ 3, si.Height) Me.Width = Me.MaximumSize.Width 'Retrieve chat IP. Dim ipre As New System.Text.RegularExpressions.Regex("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") Dim cip As String = InputBox("Please enter the IP address of the person that you would like to send to.", "Enter IP Address", "0.0.0.0") If Not ipre.IsMatch(cip) Then Me.Close() Exit Sub End If Me.txtChatLog.Text = "Begin chat with computer " & cip & ControlChars.CrLf tcpclient = New TcpClient() tcplistener = New TcpListener(Net.IPAddress.Parse(cip), 1234) tcplistener.Start() tcplistener.BeginAcceptTcpClient(AddressOf AcceptTcpClient, Nothing) Try tcpclient.Connect(Net.IPAddress.Parse(cip), 1234) conn = tcpclient.GetStream() Catch ex As SocketException MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) Me.Close() Exit Sub End Try End Sub #Region "Callbacks" Private Sub AcceptTcpClient(ByVal ia As IAsyncResult) tcprecieve = tcplistener.EndAcceptTcpClient(ia) inconn = tcprecieve.GetStream() Dim buf(1023) As Byte inconn.BeginRead(buf, 0, buf.Length - 1, AddressOf AcceptData, buf) End Sub Private Sub AcceptData(ByVal ia As IAsyncResult) Dim buf() As Byte = DirectCast(ia.AsyncState, Byte()) Dim str As String = System.Text.Encoding.ASCII.GetString(buf) Me.Invoke(ndinvoke, str) inconn.BeginRead(buf, 0, buf.Length - 1, AddressOf AcceptData, buf) End Sub #End Region Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click SendMsg(Me.txtNewMessage.Text) Me.txtNewMessage.Text = "" End Sub Private Sub SendMsg(ByVal msg As String) Try Dim c As Char For Each c In msg conn.WriteByte(AscW(c)) Next Me.txtChatLog.Text &= String.Format("{0}You said:{0}{0}{1}{0}{0}", ControlChars.CrLf, msg) Catch ex As SocketException MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) Me.Close() Exit Sub End Try End Sub End Class
I don't know about you, but I find that to be far less of an assault on the senses than the solid block you posted. Sure the code takes up more lines that way but that's what we have scroll bars for. Obviously it's up to you what you do but you'll be doing me at least a big favour if you adopt that style, and others to I think, and yourself.
Anyway, on to the question at hand. I'm going to make an educated guess and say that you're sending the data character by character instead of sending the entire message together. Why use Encoding.GetString at the receiving end and not use Encoding.GetBytes at the sending end?
-
Sep 26th, 2009, 12:42 PM
#15
Thread Starter
Stack Overflow moderator
Re: How to stop connection rejection
Until you posted that code, I had no idea that it existed. Sure, I'll do that.
About the coding style:
Usually I do it better, but I rewrote this one so many times, commented out lots of things, removed them, etc., and it kind of became a mess. Next time I post, it will probably be neater.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|