By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,664 Members | 1,592 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,664 IT Pros & Developers. It's quick & easy.

Socket.Receive blocks sometimes on localhost

P: n/a
I have a Windows Service application that acts as if it's an SMTP server.
Outlook connects to this service, which is always running on the localhost.
This works fine most of the time.
However, sometimes it will no longer receive anything from Outlook.
Socket.Receive would block indefinitely (actually, Socket.Poll times out,
because that's what I'm using). Outlook sends it, because when I'm stepping
through the code with the debugger, everything works.

Although this happens rarely, there is one situation where this always
happens: when Outlook has more than one message to send in a single
send/receive action, it will always block after the second MAIL command. An
example SMTP transcript:
220 localhost welcomes you to SignalMailSMTP
EHLO qualityweb
250 OK
MAIL FROM: <se****@signalmailsmtp.com>
250 Mail from se****@signalmailsmtp.com accepted
RCPT TO: <re******@signalmailsmtp.com>
250 Recipient re******@signalmailsmtp.com accepted
DATA
354 Start mail input; end with <CRLF>.<CRLF>
From: "SignalMail" <se****@signalmailsmtp.com>
To: <re******@signalmailsmtp.com>
Subject: AEX Enter Long alert
Date: Sat, 27 Sep 2003 14:03:28 +0200
Message-ID: <000701c384ef$5d1ae640$9dfc3850@qualityweb>
MIME-Version: 1.0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook, Build 10.0.4510
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
Importance: Normal

..
250 OK
MAIL FROM: <se****@signalmailsmtp.com>
250 Mail from se****@signalmailsmtp.com accepted

The RCPT is never received. This has been reproduced on three separate
computers. Also, if you (or Outlook itself) retry too fast after this
failure, it will again fail, again at the RCPT command.

Now I can solve this by adding a delay (Thread.Sleep) but that's a highly
undesirable solution, as the exact delay value to make it work probably
depends on the speed of the computer it's running on. Also, it's a bit of a
hack.

Now I'm fresh out of ideas. It seems the message gets lost on the localhost
interface, but the question is, what can I do about it?
The code I'm using to receive:
Do
If mConnected.Poll(5000000, SelectMode.SelectRead) Then
BytesReceived = mConnected.Receive(Buffer)
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
mLogTransscript.Append("A timeout has occurred.")
mLogTransscript.Append(Environment.NewLine)
If Not mTransscript Is Nothing Then
mTransscript.WriteLine("A timeout has occurred.")
End If
mLogError = True
mState = SmtpState.Quit
Return Nothing
End If
Loop While Message.IndexOf(endSequence) = -1

Hopefully someone here can help.

--
Sven Groot

Jul 21 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Have you tried Thread.Sleep(0)? That way you don't have to calculate the
exact time to sleep for different machines.

"Sven Groot" <sv*******@gmx.net> wrote in message
news:#P**************@TK2MSFTNGP11.phx.gbl...
I have a Windows Service application that acts as if it's an SMTP server.
Outlook connects to this service, which is always running on the localhost. This works fine most of the time.
However, sometimes it will no longer receive anything from Outlook.
Socket.Receive would block indefinitely (actually, Socket.Poll times out,
because that's what I'm using). Outlook sends it, because when I'm stepping through the code with the debugger, everything works.

Although this happens rarely, there is one situation where this always
happens: when Outlook has more than one message to send in a single
send/receive action, it will always block after the second MAIL command. An example SMTP transcript:
220 localhost welcomes you to SignalMailSMTP
EHLO qualityweb
250 OK
MAIL FROM: <se****@signalmailsmtp.com>
250 Mail from se****@signalmailsmtp.com accepted
RCPT TO: <re******@signalmailsmtp.com>
250 Recipient re******@signalmailsmtp.com accepted
DATA
354 Start mail input; end with <CRLF>.<CRLF>
From: "SignalMail" <se****@signalmailsmtp.com>
To: <re******@signalmailsmtp.com>
Subject: AEX Enter Long alert
Date: Sat, 27 Sep 2003 14:03:28 +0200
Message-ID: <000701c384ef$5d1ae640$9dfc3850@qualityweb>
MIME-Version: 1.0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook, Build 10.0.4510
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
Importance: Normal

.
250 OK
MAIL FROM: <se****@signalmailsmtp.com>
250 Mail from se****@signalmailsmtp.com accepted

The RCPT is never received. This has been reproduced on three separate
computers. Also, if you (or Outlook itself) retry too fast after this
failure, it will again fail, again at the RCPT command.

Now I can solve this by adding a delay (Thread.Sleep) but that's a highly
undesirable solution, as the exact delay value to make it work probably
depends on the speed of the computer it's running on. Also, it's a bit of a hack.

Now I'm fresh out of ideas. It seems the message gets lost on the localhost interface, but the question is, what can I do about it?
The code I'm using to receive:
Do
If mConnected.Poll(5000000, SelectMode.SelectRead) Then
BytesReceived = mConnected.Receive(Buffer)
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
mLogTransscript.Append("A timeout has occurred.")
mLogTransscript.Append(Environment.NewLine)
If Not mTransscript Is Nothing Then
mTransscript.WriteLine("A timeout has occurred.")
End If
mLogError = True
mState = SmtpState.Quit
Return Nothing
End If
Loop While Message.IndexOf(endSequence) = -1

Hopefully someone here can help.

--
Sven Groot

Jul 21 '05 #2

P: n/a
Hi,

Suggestions:
1)don't store message to string, stote it as byte[] in to MemoryStream.

2) Loop While Message.IndexOf(endSequence) = -1, if message gets
bigger(contains attachment) this code kill your computer.
Store only last 5 bytes (<CRLF>.<CRLF>), which can be used to check for data
terminator.

3) put in while loop Thread.Sleep(50) or other wise this code eats 100% of
your cpu.
(Sleep only if data not available to read)

4) Use Socket.Available to see if data must be readed or just wait to arrive
(Thread.Sleep(50) )
For complete solution see www.lumisoft.ee mail server project.
It provides SMTP/POP3/IMAP working server code.

This code is easy to follow, it's well commented, but it's in c#.

I'm sure you can find many good solutions,ideas from there or even may use
whole project.
(There isn't any need to invent bicycle, because of it already exists)

If you have some SMTP specific questions, you may email iv**@lumisoft.ee.
"Sven Groot" <sv*******@gmx.net> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
I have a Windows Service application that acts as if it's an SMTP server.
Outlook connects to this service, which is always running on the localhost. This works fine most of the time.
However, sometimes it will no longer receive anything from Outlook.
Socket.Receive would block indefinitely (actually, Socket.Poll times out,
because that's what I'm using). Outlook sends it, because when I'm stepping through the code with the debugger, everything works.

Although this happens rarely, there is one situation where this always
happens: when Outlook has more than one message to send in a single
send/receive action, it will always block after the second MAIL command. An example SMTP transcript:
220 localhost welcomes you to SignalMailSMTP
EHLO qualityweb
250 OK
MAIL FROM: <se****@signalmailsmtp.com>
250 Mail from se****@signalmailsmtp.com accepted
RCPT TO: <re******@signalmailsmtp.com>
250 Recipient re******@signalmailsmtp.com accepted
DATA
354 Start mail input; end with <CRLF>.<CRLF>
From: "SignalMail" <se****@signalmailsmtp.com>
To: <re******@signalmailsmtp.com>
Subject: AEX Enter Long alert
Date: Sat, 27 Sep 2003 14:03:28 +0200
Message-ID: <000701c384ef$5d1ae640$9dfc3850@qualityweb>
MIME-Version: 1.0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook, Build 10.0.4510
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
Importance: Normal

.
250 OK
MAIL FROM: <se****@signalmailsmtp.com>
250 Mail from se****@signalmailsmtp.com accepted

The RCPT is never received. This has been reproduced on three separate
computers. Also, if you (or Outlook itself) retry too fast after this
failure, it will again fail, again at the RCPT command.

Now I can solve this by adding a delay (Thread.Sleep) but that's a highly
undesirable solution, as the exact delay value to make it work probably
depends on the speed of the computer it's running on. Also, it's a bit of a hack.

Now I'm fresh out of ideas. It seems the message gets lost on the localhost interface, but the question is, what can I do about it?
The code I'm using to receive:
Do
If mConnected.Poll(5000000, SelectMode.SelectRead) Then
BytesReceived = mConnected.Receive(Buffer)
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
mLogTransscript.Append("A timeout has occurred.")
mLogTransscript.Append(Environment.NewLine)
If Not mTransscript Is Nothing Then
mTransscript.WriteLine("A timeout has occurred.")
End If
mLogError = True
mState = SmtpState.Quit
Return Nothing
End If
Loop While Message.IndexOf(endSequence) = -1

Hopefully someone here can help.

--
Sven Groot

Jul 21 '05 #3

P: n/a
"Sven Groot" <sv*******@gmx.net> wrote
If mConnected.Poll(5000000, SelectMode.SelectRead) Then
BytesReceived = mConnected.Receive(Buffer)
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else


Why do you use Poll with such a huge number? You can better call Receive
directly without using Poll. Receive will block until data is available.

BytesReceived = mConnected.Receive(Buffer)
If Buffer > 0 Then
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
' other side closed connection, or timeout
End If

I also agree with Ivar about the checking of only the last few bytes instead
of using IndexOf on the entire message.
You may also want to consider using a StringBuilder instance instead of
concatenating strings. This will greatly enhance the performance.

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl
Jul 21 '05 #4

P: n/a
Hi,
This code won't work. It's allowed that there isn't always data
available(you must wait to recieve it).

BytesReceived = mConnected.Receive(Buffer)
If Buffer > 0 Then
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
' other side closed connection, or timeout
End If

You may also want to consider using a StringBuilder instance instead of
concatenating strings Playing with big strings isn't good idea if that's not needed, using raw
byte data gives multiple times faster result and
there isn't any afraid of messing conent with Encoding conversation.

"Pieter Philippaerts" <Pi****@nospam.mentalis.org> wrote in message
news:es**************@tk2msftngp13.phx.gbl... "Sven Groot" <sv*******@gmx.net> wrote
If mConnected.Poll(5000000, SelectMode.SelectRead) Then
BytesReceived = mConnected.Receive(Buffer)
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived) Else
Why do you use Poll with such a huge number? You can better call Receive
directly without using Poll. Receive will block until data is available.

BytesReceived = mConnected.Receive(Buffer)
If Buffer > 0 Then
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
' other side closed connection, or timeout
End If

I also agree with Ivar about the checking of only the last few bytes

instead of using IndexOf on the entire message.
You may also want to consider using a StringBuilder instance instead of
concatenating strings. This will greatly enhance the performance.

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl

Jul 21 '05 #5

P: n/a

I see you have SSL/TLS and now it's free, will it stay free and is it usable
for SMTP,POP3(TLS).

"Pieter Philippaerts" <Pi****@nospam.mentalis.org> wrote in message
news:es**************@tk2msftngp13.phx.gbl...
"Sven Groot" <sv*******@gmx.net> wrote
If mConnected.Poll(5000000, SelectMode.SelectRead) Then
BytesReceived = mConnected.Receive(Buffer)
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived) Else
Why do you use Poll with such a huge number? You can better call Receive
directly without using Poll. Receive will block until data is available.

BytesReceived = mConnected.Receive(Buffer)
If Buffer > 0 Then
Message &= Text.Encoding.ASCII.GetString(Buffer, 0, BytesReceived)
Else
' other side closed connection, or timeout
End If

I also agree with Ivar about the checking of only the last few bytes

instead of using IndexOf on the entire message.
You may also want to consider using a StringBuilder instance instead of
concatenating strings. This will greatly enhance the performance.

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl

Jul 21 '05 #6

P: n/a
Ivar wrote:
Hi,

Suggestions:
1)don't store message to string, stote it as byte[] in to
MemoryStream.
I need it as a string. I'm not writing a real SMTP server. I'm writing
something that only deals with a *very* small amount of possible messages. I
do no forwarding, no actual mail delivery. The subject is parsed out of the
message and used for entirely different purposes. The only client that will
ever use this server is Microsoft Outlook 2000.
2) Loop While Message.IndexOf(endSequence) = -1, if message gets
bigger(contains attachment) this code kill your computer.
Store only last 5 bytes (<CRLF>.<CRLF>), which can be used to check
for data terminator.
The messages will *never* be bigger than one line of plain text body.
3) put in while loop Thread.Sleep(50) or other wise this code eats
100% of your cpu.
(Sleep only if data not available to read)
I don't see why, it doesn't go through the loop if there's no data.
4) Use Socket.Available to see if data must be readed or just wait to
arrive (Thread.Sleep(50) )
That might be a good idea. I'll try to replace Poll with a check on
Available, see if it works.
For complete solution see www.lumisoft.ee mail server project.
It provides SMTP/POP3/IMAP working server code.


It seems you misunderstood my intentions somewhat, but your advice is
appreciated. I'm not writing an actual SMTP server. What we want to do is
quite different, but the application that generates the alerts I'm trying to
catch can only send mail using MAPI, which is why I have a 'fake' SMTP
server to catch these alerts. Outlook isn't used for anything else so this
is the only mail the system has to contend with. I also agree I need to work
on performance a bit, although there's only two computers on the planet this
will ever run on, I know exactly how fast they are, and I know exactly how
frequent this code will be called.

--
Sven Groot

Jul 21 '05 #7

P: n/a
I don't see why, it doesn't go through the loop if there's no data. Data income aren't always continuous.

For example allowed(happes in real life very usually) of while loop

data_part
data_part
data_part

no data (Socket.Avaliable=0, must sleep there)
no data (Socket.Avaliable=0, must sleep there)
no data (Socket.Avaliable=0, must sleep there)

data_part

no data (Socket.Avaliable=0, must sleep there)

You must read while data terminator or time out !!!
That is very usual that there isn't 0.5 sec data available and your while
loops x times of max CPU.


"Sven Groot" <sv*******@gmx.net> wrote in message
news:ed****************@TK2MSFTNGP12.phx.gbl... Ivar wrote:
Hi,

Suggestions:
1)don't store message to string, stote it as byte[] in to
MemoryStream.
I need it as a string. I'm not writing a real SMTP server. I'm writing
something that only deals with a *very* small amount of possible messages.

I do no forwarding, no actual mail delivery. The subject is parsed out of the message and used for entirely different purposes. The only client that will ever use this server is Microsoft Outlook 2000.
2) Loop While Message.IndexOf(endSequence) = -1, if message gets
bigger(contains attachment) this code kill your computer.
Store only last 5 bytes (<CRLF>.<CRLF>), which can be used to check
for data terminator.
The messages will *never* be bigger than one line of plain text body.
3) put in while loop Thread.Sleep(50) or other wise this code eats
100% of your cpu.
(Sleep only if data not available to read)


I don't see why, it doesn't go through the loop if there's no data.
4) Use Socket.Available to see if data must be readed or just wait to
arrive (Thread.Sleep(50) )


That might be a good idea. I'll try to replace Poll with a check on
Available, see if it works.
For complete solution see www.lumisoft.ee mail server project.
It provides SMTP/POP3/IMAP working server code.


It seems you misunderstood my intentions somewhat, but your advice is
appreciated. I'm not writing an actual SMTP server. What we want to do is
quite different, but the application that generates the alerts I'm trying

to catch can only send mail using MAPI, which is why I have a 'fake' SMTP
server to catch these alerts. Outlook isn't used for anything else so this
is the only mail the system has to contend with. I also agree I need to work on performance a bit, although there's only two computers on the planet this will ever run on, I know exactly how fast they are, and I know exactly how
frequent this code will be called.

--
Sven Groot

Jul 21 '05 #8

P: n/a
Ivar wrote:
I don't see why, it doesn't go through the loop if there's no data.

Data income aren't always continuous.


I know that, and what you say is definitely true when using Available, but
not necessarily when using Poll (because it does the sleeping for you).

Anyway, using Available instead of Poll solved my original problem, so
thanks!

--
Sven Groot

Jul 21 '05 #9

P: n/a
"Ivar" <iv**@lumisoft.ee> wrote in message
This code won't work. It's allowed that there isn't always data
available(you must wait to recieve it).
That is not true. This is from the .NET documentation: "The Blocking
determines the behavior of this method when no incoming data is available.
When false, a SocketException is thrown. When true, this method blocks and
waits for data to arrive." Note that "true" is the default value for the
Blocking property, so my code works perfectly. [And if you still don't
believe it, try it yourself :-)]
Playing with big strings isn't good idea if that's not needed, using raw
byte data gives multiple times faster result and
there isn't any afraid of messing conent with Encoding conversation.


As Sven mentioned, the server isn't going to be used for large emails and
working with strings in this case is much more straightforward. Also note
that the speed of the ASCII encoding class is quite good, so it shouldn't be
a problem for large emails.

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl
Jul 21 '05 #10

P: n/a
"Ivar" <iv**@lumisoft.ee> wrote in message
I see you have SSL/TLS and now it's free, will it stay free and is it usable for SMTP,POP3(TLS).


Yes, it will stay free and yes it can be used for SMTP/POP3 [in fact, one of
the example projects is an SMTP server with TLS support].

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl
Jul 21 '05 #11

P: n/a
Yes, it will stay free and yes it can be used for SMTP/POP3 [in fact, one of the example projects is an SMTP server with TLS support]. Can you give me sample link ?

Can your library used with project as
http://www.lumisoft.ee/lsWWW/ENG/Pro...aspx?type=info
?

"Pieter Philippaerts" <Pi****@nospam.mentalis.org> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl... "Ivar" <iv**@lumisoft.ee> wrote in message
I see you have SSL/TLS and now it's free, will it stay free and is it usable
for SMTP,POP3(TLS).


Yes, it will stay free and yes it can be used for SMTP/POP3 [in fact, one

of the example projects is an SMTP server with TLS support].

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl

Jul 21 '05 #12

P: n/a
"Ivar" <iv**@lumisoft.ee> wrote in message
Can you give me sample link ?
Download the library and look under the \Samples\SSL\SmtpClient directory.
I noticed that I wrote that the library shipped with an SMTP server example
in my previous post, but it's a client not a server.
Can your library used with project as

http://www.lumisoft.ee/lsWWW/ENG/Pro...aspx?type=info

If you have the source code of that project, you can modify their mail
server to make it work with the SecureSocket.

Regards,
Pieter Philippaerts
Managed SSL/TLS: http://www.mentalis.org/go.php?sl
Jul 21 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.