473,378 Members | 1,436 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Socket.Receive blocks sometimes on localhost

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
12 3775
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
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
"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
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

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
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
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
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
"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
"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
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
"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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: mjcast | last post by:
I have been working on an ActiveX control in C#. It is packaged in a Windows Control library and the code is in a user control. The control is used as an automation receiver that is used to update a...
5
by: Terry | last post by:
It's my understanding of UDP sockets that if there is a thread blocked on a "recvFrom()" call and other thread sends a UDP packet to some address, that if the machine on the other end isn't up,...
2
by: Droopy | last post by:
Hi, I try to implement a reusable socket class to send and receive data. It seems to work but I have 2 problems : 1) I rely on Socket.Available to detect that the connection is closed (no...
1
by: Laura T. | last post by:
Hi, I've this kind a program, using sockets to communicate with the clients. One of the clients can be a web browser (like IE). When using IE as a client, the transmission blocks completely, and...
3
by: Sven Groot | last post by:
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,...
2
by: Nuno Magalhaes | last post by:
I've got a simple problem I guess. How do I know when a connection is terminated without losing any data? I do something like the code below, but sometimes between socket.Receive and socket.Send...
6
by: Pat B | last post by:
Hi, I'm writing my own implementation of the Gnutella P2P protocol using C#. I have implemented it using BeginReceive and EndReceive calls so as not to block when waiting for data from the...
0
by: petr.poupa | last post by:
Hello, I am beginner but so I need help. I have small script for receive data from port 3883, but it print only once. import socket HOST = 'localhost' PORT = 3883 s =...
1
by: Jean-Paul Calderone | last post by:
On Mon, 12 May 2008 08:34:07 -0700 (PDT), petr.poupa@gmail.com wrote: You cannot reconnect a socket. You need to create a new one for each connection. It's also almost certainly the case that...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.