I'd like to have a TCP connection for a gaming application. It's important to be time efficient. I want to receive many objects efficiently. It's also important to be CPU efficient because of the load.
So far, I can make sure handleConnection is called every time a connection is dialed using go's net library. However once the connection is created, I have to poll (check over and over again to see if new data is ready on the connection). This seems inefficient. I don't want to run that check to see if new data is ready if it's needlessly sucking up CPU.
I was looking for something such as the following two options but didn't find what I was looking for.
(1) Do a read operation that somehow blocks (without sucking CPU) and then unblocks when new stuff is ready on the connection stream. I could not find that.
(2) Do an async approach where a function is called when new data arrives on the connection stream (not just when a new connection is dialed). I could not find that.
I don't want to put any sleep calls in here because that will increase the latency of responding to singles messages.
I also considered dialing out for every single message, but I'm not sure if that's efficient or not.
So I came up with code below, but it's still doing a whole lot of checking for new data with the Decode(p) call, which does not seem optimal.
How can I do this more efficiently?
func handleConnection(conn net.Conn) {
dec := gob.NewDecoder(conn)
p := &P{}
for {
result := dec.Decode(p)
if result != nil {
// do nothing
} else {
fmt.Printf("Received : %+v", p)
fmt.Println("result", result, "\n")
}
}
conn.Close()
}
You say:
So I came up with code below, but it's still doing a whole lot of checking for new data with the Decode(p) call.
Why do you think that? The gob decoder will issue a Read to the conn and wait for it to return data before figuring out what it is and decoding it. This is a blocking operation, and will be handled asynchronously by the runtime behind the scenes. The goroutine will sleep until the appropriate io signal comes in. You should not have to do anything fancy to make that more performant.
You can trace this yourself in the code for decoder.Decode.
I think your code will work just fine. CPU will be idle until it receives more data.
Go is not node. Every api is "blocking" for the most part, but that is not as much as a problem as in other platforms. The runtime manages goroutines very efficiently and delegates appropriate signals to sleeping goroutines as needed.
I'm working with TcpStream. The basic structure I'm working with is :
loop {
if /* new data in the stream */ { /* handle it */ }
/* do a lot of other stuff */
}
So set_timeout() appears to be what I need, but I'm a little puzzled about how it works. The documentation says :
This function will set a timeout for all blocking operations (including reads and writes) on this stream. The timeout specified is a relative time, in milliseconds, into the future after which point operations will time out. This means that the timeout must be reset periodically to keep it from expiring.
So I would expect to have to reset the timeout each time before checking if new data is available, otherwise I would only have Err(TimeOut) after some time.
But it appears not to be the case : actually if I set a very low timeout (like 10 ms) once and for all, the loop does exactly what I want. It returns new data if there is some, and returns Err(TimeOut) if there is none.
Am I misunderstanding the documentation ? Is it safe for me to use this behavior ?
I would have expected it to work like a socket timeout, like you have as the property for sockets in most operating systems and which is available from with the programming languages with SO_TIMEOUT or similar things. With such socket timeout the timer will be started whenever you start a blocking operation on the socket, like read, write, connect. Either the operation will succeed within the time frame or the timer will be triggered and the operation fail because of a timeout. The timeout is a property of the socket and not of the operation, so there is no need to set it again before each operation.
But according to the documentation Rust implemented a completely different thing. If I interpret the documentation correctly they don't set a timeout per operation, but instead set a deadline for all operations of this type on the socket. That is, when the timer is set up to 10 seconds you can have multiple reads within this time but if there is still a read active after 10 seconds it will be stopped.
When one is used to work with socket timeouts in other languages this behavior is not the expected one and it looks like the Rust developers have similar objections to this (experimental) API. In https://github.com/rust-lang/rust/issues/15802 they suggest to rename these kind of functions from set..timeout to set..deadline to make the name reflect the behavior.
I am using the QT implementation of the TCP stack to control a robot. We exchange short msgs (<200Byte) and have a round trip time of about 8ms. After maybe 10.000 Packets in each direction, the connection slows down and i have to wait about 1 sec for the answer of my packet. If I restart my program, and reconnect, I again get the 8ms RTT.
For me it sounds like some kind of buffer is filling up but I havn't worked with TCP much, so maybe some one could give me a hint.
The problem is in the code that you're not showing. Likely the slot that gets executed on readyRead() is not emptying the buffer.
It is acceptable for the buffer not to be completely empty, say when you're reading complete lines/packets.
It is not acceptable for the buffer size to be constantly growing.
At the end of your slot reading slot, check if bytesAvailable() is non-zero. It can only be non-zero in case #1. Even then, you should be able to place an upper bound on it - say some small multiple of packet size or maximum line length. If the bound is ever exceeded, you've got a bug in your code.
It is just a wild guess, but a common catch by using qt sockets is that you need to delete the socket object by yourself ( for example with "deleteLater()") on error and disconnection.
Example code:
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
The event loop will then remove the socket the next time it is able to do it.
The QTcpSockets or AbstractSockets don't delete themselfs on close() or on leaving the scope (because then the Signal/Slots won't work).
i have a proxy server running on my local machine used to cache images while surfing. I set up my browser with a proxy to 127.0.0.1, receive the HTTP requests, take the data and send it back to the browser. It works fine for everything except large images. When I receive the image info, it only displays half the image (ex.: the top half of the google logo) heres my code:
char buffer[1024] = "";
string ret("");
while(true)
{
valeurRetour = recv(socketClient_, buffer, sizeof(buffer), 0);
if(valeurRetour <= 0) break;
string t;
t.assign(buffer,valeurRetour);
ret += t;
longueur += valeurRetour;
}
closesocket(socketClient_);
valeurRetour = send(socketServeur_, ret.c_str(),longueur, 0);
the socketClient_ is non-blocking. Any idea how to fix this problem?
You're not making fine enough distinctions among the possible return values of recv.
There are two levels here.
The first is, you're lumping 0 and -1 together. 0 means the remote peer closed its sending half of the connection, so your code does the right thing here, closing its socket down, too. -1 means something happened besides data being received. It could be a permanent error, a temporary error, or just a notification from the stack that something happened besides data being received. Your code lumps all such possibilities together, and on top of that treats them the same as when the remote peer closes the connection.
The second level is that not all reasons for getting -1 from recv are "errors" in the sense that the socket is no longer useful. I think if you start checking for -1 and then calling WSAGetLastError to find out why you got -1, you'll get WSAEWOULDBLOCK, which is normal since you have a non-blocking socket. It means the recv call cannot return data because it would have to block your program's execution thread to do so, and you told Winsock you wanted non-blocking calls.
A naive fix is to not break out of the loop on WSAEWOULDBLOCK but that just means you burn CPU time calling recv again and again until it returns data. That goes against the whole point of non-blocking sockets, which is that they let your program do other things while the network is busy. You're supposed to use functions like select, WSAAsyncSelect or WSAEventSelect to be notified when a call to the API function is likely to succeed again. Until then, you don't call it.
You might want to visit The Winsock Programmer's FAQ. (Disclaimer: I'm its maintainer.)
Have you analyzed the transaction at the HTTP level i.e. checked Headers?
Are you accounting for things like Chunked transfers?
I do not have a definite answer in part because of the lack of details given here.
I'm doing some revision on an old app that is written in classic ASP/VbScript.
It has a feature to send out an e-mail to the members of the application, but because the member list is quite large, the server rejects new e-mails after the first hundred or so are sent.
I've written some code to make it send out e-mails in burst of 20, but this still doesn't work. I think that perhaps making it sleep for a second between burst might work properly.
However, I can't seem to find a Thread.Sleep type method in VbScript.
Is there one?
This routine waits any amount of time, and doesn't use CPU:
Function asp_Wait(nMilliseconds)
Dim oShell
'' VBS: Set oShell= Wscript.CreateObject("WScript.Shell")
'' ASP:
Set oShell= Server.CreateObject("WScript.Shell")
Call oShell.run("ping 1.1.1.1 -n 1 -w " & nMilliseconds,1,TRUE)
'' Option TRUE: Wait until ping is complete
'' 1000 milli-second wait is 1 second
End Function
there is also a good hta hack that should work. Look for the A Synthetic Sleep Function here:
http://www.mvps.org/scripting/rube/index.htm
You can use :
<html>
<head>
<title>Sleep</title>
</head>
<body>
<%
function Sleep(seconds)
set oShell = CreateObject("Wscript.Shell")
cmd = "%COMSPEC% /c timeout " & seconds & " /nobreak"
oShell.Run cmd,0,1
End function
Sleep(5)
response.write("End")
%>
</body>
</html>
Are you using CDO? Since this is tagged as classic ASP I'm guessing so.
If so if you can use
myMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing")=1 '(which is send using pickup)
instead of
myMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing")=2 '(which is send using port)
It's more reliable because it writes the email to file (usually C:\inetpub\mailroot\pickup) and IIS's SMTP server checks the folder for new mail and will retry if it fails the first time. The catch is you have to set up SMTP within the IIS snap in.
Sorry that this answer is not strictly related to the question, but in trying to answer a question, it just got way to big for comments.
#shahka, the difference is, when you are trying to connect to a DB, the code enters a "wait state", (like a callback), so no CPU time is used. It matters not about what the SESSION or THREAD is doing, it matter what ELSE the CPU/Core is doing.
For an example, find an older non-multi-core CPU. Setup your sample to sleep for 10 seconds, then run for 2-5 seconds or so, then sleep again for 10. Do that about 20,000 times. While it's running, try and use box, see just how responsive it is. Move windows around, watch the CPU usage, etc.
THAT gives you an exmaple of what's happening to this man's Web server. It becomes unresponsive, because the thread scheduler will tend to 'favor' the CPU/Core that is NOT "spun up" (as we call it). So, ALL web requests, OS operations, etc will happen on the OTHER core, thus over-loading it, giving it a feeling of being "spun up" as well.
Now, you have times when you can tight-loop a CPU and it will not matter. But, in all my years of programming, I've never found it necessary to write a tight loop like that (on purpose). Some of it comes back around to doing things the right way, and the wrong way. Doing something the wrong way will often WORK, but that does not mean it wworks CORRECTLY.
If you want a good example of this, go and pick just about any virus on the planet, and analyze it. You'll find that it order to do damage, they (virus writers) often have to do things the "wrong" way. Sure, it gets the job done, but it also breaks the virus on say, a different language version of Windows, or it crashes the whole machine negating it's purpose, etc.
Greg Hewgill was one of my early teachers about this type of stuff, and since I worked with him for many years, and supported, and later QA'ed his software, I learned a lot from him, much in the same waay I'm trying to tell you why your code sample is not good. strictly speaking, the code is fine. It works. It's well written. But, it does not FUNCTION correctly, and has adverse side effects that other, maaybe amature programmers who might be reading this looking for knowledge do not fully understand. THAT'S why I did not recommend your sample.
Not to my knowledge. You'll have to use some external code written in class VB or whatever to do it.
Or busy-wait (gak).
You know, this is one of those times that I think setting up a private MSMQ queue could be a Good Thing. Put the emails you want to send on the queue, and have a newly developed .NET service do the sending. That will free up your ASP.NET application, and allow you to manage your sendin' centrally!
This looks like a good hack:
http://www.ehow.com/how_2001270_sleep-asp-using-ado.html
The trick is to create an ADO connection object and then try to connect to a non-existant server. This will block for the duration of the connection object's timeout setting.
Be aware that IIS has a default ASP Script execution time-out default of 90 seconds, so running large scripts that send volumes of email this way will time-out unless you change the asp timeout.
var shell = Server.CreateObject("WScript.Shell");
shell.run("CHOICE /C:AB /D:A /T:1 > NUL", 1, true);
The answer is don't use the server to wait, use the client.
You can write a javascript that keeps calling Send() every second using setInterval until the queue is empty.Use an Ajax call to send one email using a server side script. Then on return of the ajax call you can also indicate in the html page that an email has been sent.
If you are using SQL Server with ASP classic you can use WAITFOR "query" to stall the script for seconds or even milliseconds:
WAITFOR DELAY '00:00:01.234' -- 1,234 ms