Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
August 31, 2006 Sockets won't block | ||||
---|---|---|---|---|
| ||||
When I open sockets they don't seem to like blocking, and return immediately when I do a 'receive' (with 0 bytes of data of course) The routine (client and server in 1) is as follows (excuse all the tracing 'writefln's and a few artifacts from the original C++ version :-) ---- code ---- // $Header: /home/CVS/atm/ATMsock_t.cpp,v 1.1 1980/04/16 23:53:02 graeme Exp $ // $Header: /home/CVS/atm/ATMsock_t.cpp,v 1.1 1980/04/16 23:53:02 graeme Exp $ // Author: Graeme Defty // $Date: 1980/04/16 23:53:02 $ /* This module runs tests on the ATM Socket class. */ static const char pgmid[] = "$Id: ATMsock_t.cpp,v 1.1 1980/04/16 23:53:02 graeme Exp $"; // $Source: /home/CVS/atm/ATMsock_t.cpp,v $ // //#include <fstream> //#include <signal.h> //#include <unistd.h> import std.c.time; import std.stdio; import std.string; import std.socket; //#include "ATMsock.h" //#include "assure.h" // ============ Don't think we need these any more ========== //static void //sig_h(int signo) { // cout << "Caught signal " << signo << endl; // if (signo == SIGINT) exit(0); //} // ======================================================== int main (char[][] args) { int portnum = 1234; char [] buf; char [] rcvbuf; Socket mySock; InternetAddress myAddr, farAddr; int len; int count; // struct sigaction sigact; // struct sigaction oldsigact; // first handle the arguments . . . if (args.length>2) { portnum = atoi(args[2]); } writefln("Using port number " , portnum , "."); // === Signal handling seems to be unneccessary now ==== // then set up signal handling . . . // sigact.sa_handler = sig_h; // sigemptyset (&sigact.sa_mask); // sigact.sa_flags = 0; // for (len=1; len<48; len++) { // if (sigaction(len, &sigact, &oldsigact) == -1) { // perror ("Catching Signal"); // } else { // cout << "Signal " << len << " set." << endl; // } // } if (args.length>1 && args[1] == "s") { writefln("Test begins for server . . ."); myAddr = new InternetAddress("127.0.0.1", portnum); mySock = new Socket(AddressFamily.INET, SocketType.STREAM); writefln("Server created . . ."); mySock.bind(myAddr); writefln(". . . and bound . . ."); mySock.listen(5); writefln(". . . and listening."); while (true) { Socket otherSock = mySock.accept(); assert(otherSock.isAlive); writefln("Accepted a connection . . ."); writefln("Far address is ", otherSock.remoteAddress); otherSock.blocking = true; assert(otherSock.isAlive); sleep(1); len = otherSock.receive(buf); assert(len != Socket.ERROR); assert(otherSock.isAlive); writefln("Received data (", len , ") '", buf , "'."); otherSock.send(buf); assert(otherSock.isAlive); writefln("Sent that data . . ."); // mySock.close; // writefln(". . . and closed the socket."); } } else { writefln("Test begins for client . . ."); myAddr = new InternetAddress("127.0.0.1", portnum); farAddr = new InternetAddress("127.0.0.1", 1234); for (count = 0; count < 12 ; count++) { if (count % 1000 == 0) {writefln("Done " , count);} mySock = new Socket(AddressFamily.INET, SocketType.STREAM); assert(mySock.isAlive); writefln("Client created . . ."); mySock.bind(myAddr); assert(mySock.isAlive); writefln(". . . and bound . . ."); mySock.connect(farAddr); assert(mySock.isAlive); writefln(". . . and connected."); writefln("Far address is ", mySock.remoteAddress); buf = format("This is data line ", count); len = mySock.send(buf); assert(mySock.isAlive); writefln("Sent (", len , ") '", buf , "' and received '", rcvbuf , "'."); len = mySock.receive(rcvbuf); assert(mySock.isAlive); // assert (buf == rcvbuf, "Sent and received data different!"); if (buf != rcvbuf) { writefln("ERROR: Sent '", buf , "' and received '", rcvbuf , "'."); } mySock.close(); sleep(10); } } writefln("Test Done!"); return 0; } ---- end code ---- I would appreciate any guidance. Thanks, graeme |
August 31, 2006 Re: Sockets won't block | ||||
---|---|---|---|---|
| ||||
Posted in reply to %u | Sorry, guys, I forgot to add that I am on Windows XP The output is as follows: === Client: C:>atmsock_tt c 4321 Using port number 4321. Test begins for client . . . Done 0 Client created . . . . . . and bound . . . . . . and connected. Far address is 127.0.0.1:1234 Sent (19) 'This is data line 0' and received ''. ERROR: Sent 'This is data line 0' and received ''. Client created . . . etc. === end === Server: C:\Documents and Settings\Administrator\My Documents\Projects\atm.d>atmsock_tt s Using port number 1234. Test begins for server . . . Server created . . . . . . and bound . . . . . . and listening. Accepted a connection . . . Far address is 127.0.0.1:4321 Received data (0) ''. Sent that data . . . === end Thanks again, g |
August 31, 2006 Re: Sockets won't block | ||||
---|---|---|---|---|
| ||||
Posted in reply to %u | On Thu, 31 Aug 2006 16:37:02 +0000 (UTC), %u <gdefty@attglobal.net> wrote: > When I open sockets they don't seem to like blocking, and return immediately > when I do a 'receive' (with 0 bytes of data of course) This is due to the receive function's shortcut, see std\socket.d: if(!buf.length) //return 0 and don't think the connection closed return 0; you're passing it a 0 length buffer. If you pass 0 for len to the 'recv' call it will return an error WSAEINVAL. The comment indicates a desire to avoid the error because people assume it means the socket has closed, which you could do, if you didn't check the actual error code perhaps. The solution. Your receive calls need to look something like this: buf.length = 100; len = otherSock.receive(buf); assert(len != Socket.ERROR); assert(otherSock.isAlive); buf.length = len; writefln("Received data (", buf.length , ") '", buf , "'."); In other words, allocate some space in buf, read data into buf, check for errors, set buf length to length of data read, log it to screen. I also made the client socket blocking with: mySock.blocking = true; after the connect call. Though, from memory sockets are blocking by default. One other thing I changed was your logging here: writefln("Sent (", len , ") '", buf , "' and received '", rcvbuf , "'."); I made this into 2 log lines, the 2nd _after_ the receive call :) FYI... the client does not need to call 'bind'. It's entirely optional for simple outgoing connections. If you do not call bind it will automatically bind the first random available local socket. The only time you need to call bind is when you want the remote connection to see you as a certain ip and/or port. Regan > The routine (client and server in 1) is as follows (excuse all the tracing > 'writefln's and a few artifacts from the original C++ version :-) > > ---- code ---- > // $Header: /home/CVS/atm/ATMsock_t.cpp,v 1.1 1980/04/16 23:53:02 graeme Exp $ > // $Header: /home/CVS/atm/ATMsock_t.cpp,v 1.1 1980/04/16 23:53:02 graeme Exp $ > > // Author: Graeme Defty > // $Date: 1980/04/16 23:53:02 $ > /* > This module runs tests on the ATM Socket class. > */ > > static const char pgmid[] = > "$Id: ATMsock_t.cpp,v 1.1 1980/04/16 23:53:02 graeme Exp $"; > > // $Source: /home/CVS/atm/ATMsock_t.cpp,v $ // > > //#include <fstream> > //#include <signal.h> > //#include <unistd.h> > import std.c.time; > import std.stdio; > import std.string; > import std.socket; > > //#include "ATMsock.h" > > //#include "assure.h" > > // ============ Don't think we need these any more ========== > //static void > //sig_h(int signo) { > // cout << "Caught signal " << signo << endl; > // if (signo == SIGINT) exit(0); > //} > // ======================================================== > > int > main (char[][] args) { > > int portnum = 1234; > char [] buf; > char [] rcvbuf; > Socket mySock; > InternetAddress myAddr, farAddr; > int len; > int count; > // struct sigaction sigact; > // struct sigaction oldsigact; > > // first handle the arguments . . . > if (args.length>2) { > portnum = atoi(args[2]); > } > writefln("Using port number " , portnum , "."); > > // === Signal handling seems to be unneccessary now ==== > > // then set up signal handling . . . > // sigact.sa_handler = sig_h; > // sigemptyset (&sigact.sa_mask); > // sigact.sa_flags = 0; > // for (len=1; len<48; len++) { > // if (sigaction(len, &sigact, &oldsigact) == -1) { > // perror ("Catching Signal"); > // } else { > // cout << "Signal " << len << " set." << endl; > // } > // } > > if (args.length>1 && args[1] == "s") { > > writefln("Test begins for server . . ."); > > myAddr = new InternetAddress("127.0.0.1", portnum); > mySock = new Socket(AddressFamily.INET, SocketType.STREAM); > writefln("Server created . . ."); > mySock.bind(myAddr); > writefln(". . . and bound . . ."); > mySock.listen(5); > writefln(". . . and listening."); > > while (true) { > Socket otherSock = mySock.accept(); > assert(otherSock.isAlive); > writefln("Accepted a connection . . ."); > writefln("Far address is ", otherSock.remoteAddress); > > otherSock.blocking = true; > assert(otherSock.isAlive); > sleep(1); > > len = otherSock.receive(buf); > assert(len != Socket.ERROR); > assert(otherSock.isAlive); > writefln("Received data (", len , ") '", buf , "'."); > > otherSock.send(buf); > assert(otherSock.isAlive); > writefln("Sent that data . . ."); > // mySock.close; > // writefln(". . . and closed the socket."); > } > > } else { > writefln("Test begins for client . . ."); > > myAddr = new InternetAddress("127.0.0.1", portnum); > farAddr = new InternetAddress("127.0.0.1", 1234); > > for (count = 0; count < 12 ; count++) { > if (count % 1000 == 0) {writefln("Done " , count);} > > mySock = new Socket(AddressFamily.INET, SocketType.STREAM); > assert(mySock.isAlive); > writefln("Client created . . ."); > > mySock.bind(myAddr); > assert(mySock.isAlive); > writefln(". . . and bound . . ."); > > mySock.connect(farAddr); > assert(mySock.isAlive); > writefln(". . . and connected."); > > writefln("Far address is ", mySock.remoteAddress); > > buf = format("This is data line ", count); > len = mySock.send(buf); > assert(mySock.isAlive); > writefln("Sent (", len , ") '", buf , "' and received '", rcvbuf , "'."); > > len = mySock.receive(rcvbuf); > assert(mySock.isAlive); > // assert (buf == rcvbuf, "Sent and received data different!"); > if (buf != rcvbuf) { > writefln("ERROR: Sent '", buf , "' and received '", rcvbuf , "'."); > } > mySock.close(); > sleep(10); > } > } > writefln("Test Done!"); > return 0; > } > > ---- end code ---- > > I would appreciate any guidance. > > Thanks, > > graeme |
September 02, 2006 Re: Sockets won't block - thank you | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan, Can't thank you enough for the help. All is well now. It is a bit disappointing that the 'wrapper' round the C call is so 'thin'. The sad thing is, my original C++ code allocated a 1K buffer and did all the right things. I changed it to be a dynamic array in the expectation that the buffer would be expanded as necessary. Oh well. That'll teach me :-) > I also made the client socket blocking with: mySock.blocking = true; > after the connect call. Though, from memory sockets are blocking by default. Yes, you are right. They are. > One other thing I changed was your logging here: writefln("Sent (", len , ") '", buf , "' and received '", rcvbuf , "'."); > I made this into 2 log lines, the 2nd _after_ the receive call :) Hmmm. Yes. <Sounds offstage of faces going red :-) > > FYI... the client does not need to call 'bind'. Yes. I think that was one of my 'stabs in the dark'. Anyway, Thanks again for your speedy and madly useful response. Cheers, graemeDeft |
September 03, 2006 Re: Sockets won't block - thank you | ||||
---|---|---|---|---|
| ||||
Posted in reply to Graeme Defty | On Sat, 2 Sep 2006 06:29:24 +0000 (UTC), Graeme Defty <gdefty@attglobal.net> wrote: > Can't thank you enough for the help. All is well now. You're welcome. > It is a bit disappointing that the 'wrapper' round the C call is so 'thin'. The sad thing is, my original C++ code allocated a 1K buffer and did all the right things. I changed it to be a dynamic array in the expectation that the buffer would be expanded as necessary. Oh well. That'll teach me :-) Have you seen/tried "std.socketstream"? It might be more to your liking. Regan |
Copyright © 1999-2021 by the D Language Foundation