mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 2 1 2
#229751 16/02/11 03:20 PM
Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
I've noticed an issue with some of my scripts that use sockets since using 7.xx where the data doesn't get sent instantly as it is now queued but any other socket events such as sockclose seem to be put ahead of this queue and do not produce an error that the socket didn't receive the sent data.

See example below:

Code:
on *:SOCKLISTEN:TestSocket:{
 sockaccept test.s
 echo -s socket accepted
 sockwrite -tn test.s this is a test
}
on *:SOCKREAD:test*:{
 if ($sockerr > 0) { echo -s error on socket | sockclose $sockname }
 sockread -fn &Read.test | tokenize 32 $bvar(&Read.test,1,$bvar(&Read.test,0)).text
 echo -s $sockname received: $1-
 if ($1 == dotest) {
  sockwrite -tn $sockname testing 1
  sockwrite -tn $sockname testing 2
  sockwrite -tn $sockname testing 3
  sockclose $sockname
 }
}
on *:SOCKWRITE:test*:{
 echo -s $sockname sent data
}
on *:SOCKCLOSE:test*:{
 echo -s $sockname socket closed
}
on *:SOCKOPEN:test*:{
 echo -s $sockname socket opened
 if ($sockname == test) { sockwrite -tn test dotest }
}
alias testsocket {
 socklisten TestSocket 1010
 sockopen test localhost 1010
}
alias sockwrite {
 echo -s data sent to: $2 was: $3-
 sockwrite $1-
}


Result from 7.xx:

Code:
socket accepted
data sent to: test.s was: this is a test
test socket opened
data sent to: test was: dotest
test.s sent data
test sent data
test received: this is a test
test.s received: dotest
data sent to: test.s was: testing 1
data sent to: test.s was: testing 2
data sent to: test.s was: testing 3
test socket closed


Result from earlier versions (6.35):

Code:
test socket opened
data sent to: test was: dotest
socket accepted
data sent to: test.s was: this is a test
test sent data
test.s sent data
test received: this is a test
test.s received: dotest
data sent to: test.s was: testing 1
data sent to: test.s was: testing 2
data sent to: test.s was: testing 3
test received: testing 1
test received: testing 2
test received: testing 3
test socket closed


Is this intentional? If not it means I will need to re-write my scripts that use sockets

Last edited by Rewtor; 16/02/11 03:21 PM.
Joined: Jun 2007
Posts: 933
5
Hoopy frood
Offline
Hoopy frood
5
Joined: Jun 2007
Posts: 933
Your version of 7.x matters greatly in this case? What version did you use?
Also see this previous bug report.

Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
I have seen that previous bug report and it still isn't fixed. I have used all 7.xx versions including 7.17 and my script posted still has the issue.

Did you even test it out?

Last edited by Rewtor; 16/02/11 03:42 PM.
Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
Does anyone know if this is intentional behaviour? To me it is a bug, why isn't the data being sent, not even the first sockwrite even though it is called before the closing of the socket?

Joined: Sep 2005
Posts: 2,881
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Sep 2005
Posts: 2,881
Seems intended to me.

You perform /sockwrite and the data is added to a queue.
You then immediately /sockclose before mIRC has chance to process the queue. The help file doesn't suggest that /sockclose is also queued, as there is no need for it to be.

mIRC is a single-threaded application and will process the rest of the sockread event before it deals with the send queue.

You should close the socket in the on SOCKWRITE event to do what you're trying to do.

Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
But it has ALWAYS sent it before a sockclose previously, even though it is queued there isn't anything else in the queue and therefore should be sent immediately... IMO everything should be done the order of which it is called.

It is like that in any programming language mSL included apart from these 7.xx updates...

Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
I'm not saying it's right or wrong the way it's working, but you can compare it to a timer. If you set something on a timer (i.e. queued) for 2 seconds from now and immediately turn off the timer, what you told it to do won't get done.

/sockclose really should not be sent immediately. It should be sent only when all of the data is retrieved or sent. In your example, as mentioned, that would be in the sockwrite event.

Like I said, I'm not saying it's handling this the best way possible. Many people will assume it will be handled the same way you're expecting. But with it being queued, this doesn't happen. Maybe it can be improved, but a small change in your script solves the problem as well.


Invision Support
#Invision on irc.irchighway.net
Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
I see what your saying, but in theory if you call it before the sockclose it SHOULD be done before the socket is closed, especially since nothing else is using the queue.

Lets say I wanted to fopen a text file write to it and then fclose it, its basically the same thing... the text WILL be written even though fclose was immediately called because it was called AFTER the fwrite

Last edited by Rewtor; 17/02/11 12:48 PM.
Joined: Jul 2006
Posts: 4,145
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,145
Quote:
but in theory if you call it before the sockclose it SHOULD be done before the socket is closed, especially since nothing else is using the queue.
-
Does anyone know if this is intentional behaviour? To me it is a bug, why isn't the data being sent, not even the first sockwrite even though it is called before the closing of the socket?
/sockwrite use a queue, when the command /sockwrite is done, you must not consider that data is sent
Quote:
Lets say I wanted to fopen a text file write to it and then fclose it, its basically the same thing... the text WILL be written even though fclose was immediately called because it was called AFTER the fwrite
The difference is that /fopen /fwrite and /fclose will block mirc until the file is opened/closed/written, /sockwrite won't since it's queued.

There have been some changes in socket with the 7.x versions, and unicode didn't help speeding the engine. The help file states that mirc try to send the data as fast as possible, it just seems that 6.35 was able to handle your three /sockwrite (or your use of socket in general, since you didn't see that earlier) before /sockclosing the socket.


Last edited by Wims; 17/02/11 01:41 PM.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Sep 2005
Posts: 2,881
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Sep 2005
Posts: 2,881
Originally Posted By: /help /sockwrite
/sockwrite [-tnb] <name> [numbytes] <text|%var|&binvar>

The /sockwrite command queues info to be sent on the specified connection. mIRC will then try to send that info as quickly as it can. Once it has finished sending the info, it triggers the on sockwrite event so you can send more info if you need to.


This has been the description for the sockwrite command as long as I can remember. If the data was sent immediately there would be no point in the on sockwrite event, would there? You could just assume that as soon as the /sockwrite command finished the data was sent.

The behaviour may be different to what it was in previous versions, I don't know, but closing a socket immediately after attempting to send data is bad practice anyway. Use the on sockwrite event, that's what it's there for.

Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
But that would mean my code would need to be longer because the sockwrite event doesn't pass what was written and to where, you are required to do this by redefining the sockwrite alias and will make things messy.

I understand that there is a queue involved but as I said before if nothing is in the queue why isn't it sent instantly?

And my use of fopen etc was just an example to show that it should be processed in the order it is set otherwise it is unreliable, you could have someone on a custom banlist and have your message to the channel stating they are banned with a kick afterwards but the kick would be done first... It's just not logical.

But if this is how Khaled wants the sockwrite to work at least add a switch so we can bypass the queue?

Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
Originally Posted By: hixxy
Originally Posted By: /help /sockwrite
/sockwrite [-tnb] <name> [numbytes] <text|%var|&binvar>

The /sockwrite command queues info to be sent on the specified connection. mIRC will then try to send that info as quickly as it can. Once it has finished sending the info, it triggers the on sockwrite event so you can send more info if you need to.


This has been the description for the sockwrite command as long as I can remember. If the data was sent immediately there would be no point in the on sockwrite event, would there? You could just assume that as soon as the /sockwrite command finished the data was sent.

The behaviour may be different to what it was in previous versions, I don't know, but closing a socket immediately after attempting to send data is bad practice anyway. Use the on sockwrite event, that's what it's there for.


I know that has been in the help file for ages (for as long as I can remember also), but the queues WERE still working in 6.35 but the info was sent instantly IF there wasn't a queue but if loads of data had been sent the $sock().sq would build up so it WAS correct behaviour before 7.xx

Also there isn't any point to the sockwrite event because the only information you can get from it is anything to do with $sock() and $sockname, not what was actually written.

So trying to perform several sockwrites on multiple sockets you wouldn't be able to deal with what was needed after the sockwrites, this is bad for people that use socket connections etc..

Last edited by Rewtor; 17/02/11 02:28 PM.
Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
As said before and in my opinion, instead of Khaled adding a switch to sockwrite, I think you should not close the socket until you are finished with it.

Another thing I noticed, I dunno, maybe you were testing, but

$bvar(&Read.test,1,$bvar(&Read.test,0)).text

should be the same as: $bvar(&Read.test,1-).text

Joined: Sep 2005
Posts: 2,881
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Sep 2005
Posts: 2,881
If you need to do something with the data that was sent then just make a new alias. This is what I used to do:

Code:
alias send {
  if ($sock(blabla)) { 
    sockwrite -n blabla $1- 
    if ($window(@debug)) { aline @debug >>> $1- }
  }
}


Then you just call /send <data>

This behaviour is very similar as to why /sockwrite won't work directly after /sockopen and why you have to wait for the on SOCKOPEN event. mIRC is a single-threaded application and doesn't begin to process the socket messages until it has finished processing the current script.

I'm not even sure how/why it used to work as you describe.

Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
Originally Posted By: DJ_Sol
As said before and in my opinion, instead of Khaled adding a switch to sockwrite, I think you should not close the socket until you are finished with it.

Another thing I noticed, I dunno, maybe you were testing, but

$bvar(&Read.test,1,$bvar(&Read.test,0)).text

should be the same as: $bvar(&Read.test,1-).text


Thanks for the bit below, didn't realise you could do that with binvars. As for not closing until I am finished with it, I AM finished after I have sent the data I need to which is why it is then closed.

@hixxy that is basically the same as rewriting the sockwrite alias as done in the script above to see what had been sent. That is the ONLY way you can see what data was sent, even then the echo would appear once sockwrite was called NOT when it was sent so actually both the rewriting of this alias and the sockwrite event are practically useless in checking what has been SENT in order to continue what you need to do...

For as long as I have used mIRC this has always worked fine, up until the newer 7.xx versions and I don't see the point in rewriting my scripts just to make them even longer than what they are now and even then they won't be very accurate because I can't check when it is sent.

It would easily make a 500 line file 1000 lines.. I know I won't be using any 7.x versions if this is how it's going to stay.

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
This is the intended and expected behaviour and applies to older versions of mIRC as well.

This issue may be more apparent in newer versions of mIRC due to a few changes to how sockets are handled, however it is in fact present in all versions of mIRC.

Sockets are asynchronous, which means that they send data in the background when they can. There is no guarantee that data can be sent immediately in Windows sockets. An attempt to send data may in fact block, or send only partial data, in which case mIRC will try to send any remaining data when Windows indicates it is ready for more.

When using sockets, you should never assume that you can close a socket immediately after sending data. You should wait until on SOCKWRITE has triggered, as described in the help file, and check the send queue to see if it is empty before closing the socket.

Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
Originally Posted By: Khaled
This is the intended and expected behaviour and applies to older versions of mIRC as well.

This issue may be more apparent in newer versions of mIRC due to a few changes to how sockets are handled, however it is in fact present in all versions of mIRC.

Sockets are asynchronous, which means that they send data in the background when they can. There is no guarantee that data can be sent immediately in Windows sockets. An attempt to send data may in fact block, or send only partial data, in which case mIRC will try to send any remaining data when Windows indicates it is ready for more.

When using sockets, you should never assume that you can close a socket immediately after sending data. You should wait until on SOCKWRITE has triggered, as described in the help file, and check the send queue to see if it is empty before closing the socket.


Hi Khaled, thanks for looking into this however, I already mentioned that queueing was working in older versions but it was still sent instantly if nothing was in the queue, why doesn't 7.xx do this? Surely if nothing is in the queue then it should send when it is called?

And using the sockwrite event I cannot see what was actually wrote to the socket, therefore I cannot perform specific actions based on what was sent plus this would double the size of a script because I will be checking what needs to be sent and then checking it again once it has been sent and performing the necessary

edit: also why are all sockets treated as asynchronous? UDP sockets are asynchronous where as TCP should be synchronous because both sides need to make acknowledgements?

Last edited by Rewtor; 17/02/11 03:46 PM.
Joined: Jul 2006
Posts: 4,145
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,145
Quote:
I already mentioned that queueing was working in older versions but it was still sent instantly if nothing was in the queue, why doesn't 7.xx do this?
I more or less explained that, 6.35 was just faster than 7.xx, you were just lucky that your socket code worked
Quote:
And using the sockwrite event I cannot see what was actually wrote to the socket, therefore I cannot perform specific actions based on what was sent plus this would double the size of a script because I will be checking what needs to be sent and then checking it again once it has been sent and performing the necessary
As stated several times, the on sockwrite event only tell you when you can send informations again, I think Khaled couldn't fill $1- with what was sent even if he wanted to, not sure though. We are just telling you that it's not a bug because it's how sockets work, size of scripts doesn't matter.
Quote:
also why are all sockets treated as asynchronous? UDP sockets are asynchronous where as TCP should be synchronous because both sides need to make acknowledgements?
asynchronous doesn't mean "not connected", it means that a call to a socket function won't lock the program.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Sep 2006
Posts: 59
R
Rewtor Offline OP
Babel fish
OP Offline
Babel fish
R
Joined: Sep 2006
Posts: 59
Well either way this isn't the way I have always used sockets with mIRC along with MANY other people, just look for a popular script that uses sockets. SO i'll just stick to 6.35

Joined: Sep 2005
Posts: 2,881
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Sep 2005
Posts: 2,881
Originally Posted By: Rewtor
Well either way this isn't the way I have always used sockets with mIRC along with MANY other people, just look for a popular script that uses sockets. SO i'll just stick to 6.35


The thing is, as Khaled said, "This is the intended and expected behaviour and applies to older versions of mIRC as well."

In other words the older versions behaved the same way. It's sheer luck that your script runs fast enough to send the data before calling /sockclose, but it won't be like that for everyone who uses your script.

Why are you being so stubborn about this, what's so hard about using the on sockwrite event?

Page 1 of 2 1 2

Link Copied to Clipboard