Commonly Asked Questions and Answers for LWP Toolkit ---------------------------------------------------- Q: Is there WINSOCK support for LWP? A: It will be available on Netwire in the Fall 1993. Q: How do I detect when the remote host has dropped the connection unexpectedly? ie. you pull the plug, or disconnect the network cable. A: Use setsockopt() on the client side to enable KEEPALIVES. A packet with just '?' for data is sent out every 75 seconds. The other side should recognize this as a KEEPALIVE packet and send back an ACK. If the client doesn't receive the acknowledgement within another 75 seconds the socket will be closed. Any socket calls you make after that will return -1 and have errno=EBADF (as long as that function uses the socket descriptor - not things like bcopy()). Note that you must call setsockopt() BEFORE connect()! Q: What if I'm in the middle of a blocking recv() on the client side, KEEPALIVES on, and I pull the plug on the remote host. Will LWP close down that socket and return recv() with -1, errno=EBADF? A: Yes it will close down the socket and recv() returns with -1 but if you have the latest tcpip from Netwire errno=ECONNRESET instead of EBADF. (Type "version tcpip" and you get something like this: ....DOS TCPIP v4.1 (R41-1n, 930727) - version R41-1n or later, say R41-1o, is what I mean here.) Q: I am using select() and the socket is always ready for writing, and showing an exception. Why? A: These features were not implemented in tcpip R41. In tcpip v4.1 R41-1n (or later) we have support for the write descriptors. Q: What is the difference between write() and send()? A: None in the original tcpip v4.1 (the one that came on the diskettes), because we didn't support any flags on the send(). In v4.1 R41-1f we added support for sending Out Of Band data but that is the only difference. The latest LWP41 patch on Netwire includes features added in earlier versions such as 41-1f. Q: I am writing a DOS client for the UNIX server. How will I know when a client has gone down? A: When the client closes its socket normally the server should not have a problem. It's when you Ctrl-C out of the DOS tcpip app. that you get a surprise. In the DOS/LWP world sockets are not tied in with the application and are not closed by DOS when you kill the application like this. So even if you are running KEEPALIVES on your UNIX the LWP tcpip will still have those sockets open and ACK the UNIX's KEEPALIVES. You need to add an interrupt handler for Ctrl-C to your LWP app and from there close all open sockets. You may also want to look at the _abort_oper() function. Q: What is the maximum length of buffer I should be able to write with one call to sowrite() ? A: 32K but you will need to increase the Mempool in your net.cfg. Some data is buffered by the tcpip stack and with the default Mempool of 4096 you can write about 12K at once. Mempool is also used to store outgoing data so once you increase that you can write up to 32K at once, providing the remote host is advertising a Window size of at least 32K. The default window size in our tcpip is only 2880 (bytes). If you get tcpip version v.4.1N (R41-1n) from Netwire then you can increase the Window size to 32767 with a tcp_window statement in the net.cfg Q: How are LSL Buffers related to data flow? A: These are buffers for incoming data. Increasing the number of buffers should increase the number of bytes you can read in one soread() call, provided you have increased your Window size, and there's that much data there to be read... Q: What is the maximum number of sockets I can use at once? A: 128 tcp + 64 udp. You may notice that if you open a socket and make a connection, then close the socket that descriptor doesn't become available until the other side has closed its socket or 2 minutes have expired. If you use LWPCON you'll see the socket in a CLOSING state. This is part of the TCP protocol. Read Comer's Internetworking with TCP/IP Volume II page 194 for an explanation. Q: When I restart my server I get "Address already in use" from bind(). A: First you need to close the original socket that is using that port number. If you hit Ctrl-C to quit the program and didn't write your own interrupt handler to close that socket, then its probably still in a LISTENING state. (Use LWPCON to see the state of your sockets.) You could do: for (i=0; i<128; soclose(i), i++); before creating the socket and then do setsockopt(REUSEADDR) before the bind. Now you should be able to reuse that port. Of course this would also close all other tcpip apps that were running. Q: How do I know when my connect() has completed if I'm using non-blocking I/O ? A: Keep calling connect() until errno=EISCONN. The first call to connect() will put errno=EINPROGRESS, then you'll get errno=EALREADY and finally errno=EISCONN (if the connection succeeds). Q: How long does it take for a blocking connect() to timeout? A: 75 seconds. Not configurable but if you use non-blocking connects with time(), you can loop on connect()s until errno=EISCONN, or x seconds have passed. In Windows use GetTickCount() instead of time(). Q: What is the maximum number of pending asynchronous calls I can have? A: 16 total for all Windows apps, 16 per app in DOS. An ENO_RCBS error may indicate you've exceeded 16. Q: Is there a way to cancel pending asynchronous calls? A: Yes, close that socket. Q: What socket options does LWP4.1 support? A: KEEPALIVE and REUSEADDR. Q: How can I broadcast a message? A: Open a UDP socket and then sendto() to your network's broadcast address. addr.sin_addr.s_addr = inet_addr("255.255.255.255"); rc = sendto (s, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&addr, sizeof(addr)); Q: We wrote an application for LWP4.01, will it run on LWP4.1? A: Yes, provided you did not access unsupported/undocumented structures in 4.01. Although 4.1 uses PATH statements in the net.cfg to find files in \NET\TCP directory (ex. hosts file), if your application was compiled with 4.01 you still need to 'set excelan=c:\xln'. For Windows apps add 'Root=c:\xln' to the top of your lwp.ini. Q: I get "symbol not defined" errors from the compiler when I do: ioctl(FIONBIO). A: Use soioctl() with Borland. They have their own ioctl() so we renamed ours. Q: Do any of the socket API functions use DOS interrupt 21? A: Only the host database functions (gethostbyname, getnetbyname, rhost...). Q: Is there a way for a Windows program to check if vtcpip.386 has been loaded? A: Not directly. The best you can do is to use the Windows INI routines to see if there is a device=vtcpip.386 in system.ini. Q: Can I do ICMP ? A: No, we do not support raw sockets. Q: I'm having trouble writing an FTP or TELNET client. A: Look for examples and specs in the following: 1. Internetworking with TCP/IP by Douglas Comer, Prentice Hall. 2. UNIX Network Programming by W.Richard Stevens, Prentice Hall. 3. The RFCs (Request for Comments). These are the set of documents that define the Internet Protocols. Appendix 1 in Comer tell you how to get these. nic.ddn.mil is one place for anonymous ftp. IP (Internet Protocol) RFC 791 TCP (Transmission Control Protocol) RFC 793 (0-64 sockets) UDP (User Datagram Protocol) RFC 768 (0-32 sockets) TELNET (Telnet Protocol) RFC 854 FTP (File Transfer Protocol) RFC 959 TFTP (Trivial File Transfer Protocol) RFC 783 4. BSD sources are available on the Internet. Use archie to find what you need. Q: I'm having trouble compiling/linking the sample windows programs for Borland's C++. A: Add them as items to your project. For instance, to make the wtcpserv sample program open a new project and add wtcpserv.c, wtcpserv.rc, twlbsock.lib as items in that project. Linker settings: Default Libraries. Note that the link is NOT case sensitive. If you want to do case sensitive linking, create your own import library : "IMPLIB myimp.lib wlibsock.dll" Source code extention should be *.C, not *.CPP. Specify the path for the header files and libraries under Options->Directories. For Windows apps you also need to #define WINDOWS under Options->Compiler->Code Generation->Defines. ------------------------------------------------------------------ # Makefile for wtcpserv and wtcpclnt sample programs # Type: make -DPROG=wtcpserv # make -DPROG=wtcpclnt $(PROG).exe : $(PROG).obj $(PROG).res $(PROG).def tlink /Tw /v /n /c c0ws $&, $&, , twlbsock cws cs import, $& rc $*.res .c.obj : BCC -c -ms -v -W -DWINDOWS $< .rc.res : rc -r -iC:\borlandc\INCLUDE $< ------------------------------------------------------------------- Q: There is no gethostname() function to get my local host's name. How can I do this? A: Do getmyipaddr() followed by gethostbyaddr() or raddr(). Q: Why isn't gethostbyname() finding my resolv.cfg ? A: It just looks at your local hosts file. You need to use rhost() for DNS. Q: I'm having trouble using gethostbyname()/gethostbyaddr() in Windows. A: The hostent fields are OFFSETS to the name,address aliases, etc. To access the values of those field take the pointer to the hostent structure and add the offset. In DOS you get the fields themselves, not offsets and can access the values directly. Here's how you get the hostname: pHost = (struct hostent far *) GlobalLock(hTemp); pHostName = (char far *)pHost; pHostName += pHost->h_name; Q: Does LWP tcpip use the Nagle algorithm? A: No, as soon as you write any data it is sent (providing other party's windows size > 0). Q: How do I find out what local port my socket is using? A: Do a bind() with your IP address and port number set to 0. The transport will assign you a port number which you can get by then calling getsockname().