Thank you, Anonymous Poster! [grin]
ok, I'm getting somewhere... :)
here is some basic code, for anyone remotely interested
#include <stdlib.h> // for rand functions#include <stdio.h>#include <math.h>#define NET_WINSOCK_VERSION 0x0202#include <winsock2.h>#include <windows.h>#include <conio.h>#pragma comment(lib, "ws2_32.lib")class NetLib_SendStream{public:private:};class NetLib_RecvStream{public:private:};class NetLib_Socket{public: NetLib_Socket(const char* _name) { if(_name == NULL) _name = "noname"; name = new char[strlen(_name) + 1]; strcpy(name, _name); sendstream = new NetLib_SendStream; recvstream = new NetLib_RecvStream; port = 0; state = LIMBO; sock = 0; ZeroMemory(ip, sizeof(ip)); ZeroMemory(&address, sizeof(address)); } ~NetLib_Socket() { CloseSocket(); delete sendstream; delete recvstream; delete[] name; } bool Listen(int _port) { Output("starting server..."); CloseSocket(); strncpy(ip, "127.0.0.1", 16); ip[15] = '\0'; port = _port; sock = socket(AF_INET, SOCK_DGRAM, 0); if(sock == 0) { Output("failed to create socket."); CloseSocket(); return false; } Output("socket created."); if (!SetOptions(false, true, true, false, 16 * 1024)) { CloseSocket(); return false; } // scan ports int i; for(i = 0; i < 100; i ++, port++) { address.sin_family = AF_INET; address.sin_port = htons(port); address.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (LPSOCKADDR)&address, sizeof(address)) == SOCKET_ERROR) { if(WSAGetLastError() != WSAEADDRINUSE) { Output("failed to bind."); CloseSocket(); return false; } else { Output("port(%d) in use.", port); } } else { break; } } if(i == 100) { Output("failed to find available port."); CloseSocket(); return false; } Output("bind successful."); Output("server address is %s:%d.", ip, port); Output("waiting for connection."); state = LISTENING; return true; } bool SetOptions(bool bsetReusable, bool bnonBlocking, bool ballowBroadcasting, bool bkeepAlive, int receiveBufferSize) { WSAPROTOCOL_INFO protocolInfo; unsigned long nonBlocking = bnonBlocking? 1 : 0; int allowBroadcasting = ballowBroadcasting? 1 : 0; int keepAlive = bkeepAlive? 1 : 0; if(bsetReusable) { int yes = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(int)) == SOCKET_ERROR) { Output("failed to set reusable socket."); } else { Output("socket is reusable."); } } if(ioctlsocket(sock, FIONBIO, &nonBlocking) == SOCKET_ERROR) { Output("failed to set non-blocking state."); } else { Output("socket is set to %s", nonBlocking? "non-blocking" : "bloking"); } if(setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &keepAlive, sizeof (int)) == SOCKET_ERROR) { Output("failed to set keepalive state."); } else { Output("keepalive set to %s.", keepAlive? "true" : "false"); }/**/ if(setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *) &receiveBufferSize, sizeof (int)) == SOCKET_ERROR) { Output("failed to set receivebuffer size."); } else { Output("receivebuffer size set to %dkB.", receiveBufferSize / 1024); } if(setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &allowBroadcasting, sizeof (int)) == SOCKET_ERROR) { Output("failed to broadcast state."); } else { Output("set broadcast %s.", allowBroadcasting? "on" : "off"); } int protocolstructlen = sizeof(protocolInfo); if (getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFO, (char*) &protocolInfo, &protocolstructlen) == SOCKET_ERROR) { Output("failed to get protocol info."); } else { if(protocolstructlen != sizeof(protocolInfo)) { Output("mismatch in protocol structures."); } else { #define OUTPROVIDER(x) Output(" [%s] " #x, (protocolInfo.dwProviderFlags & (x))? "X" : " "); #define OUTSERVICES(x) Output(" [%s] " #x, (protocolInfo.dwServiceFlags1 & (x))? "X" : " "); Output("---------------------------"); Output("PROTOCOL INFO"); Output("- Version : %d", protocolInfo.iVersion); Output("- Protocol : %d", protocolInfo.iProtocol); Output("- Protocol Name : %s", protocolInfo.szProtocol); Output("- Socket Type : %d", protocolInfo.iSocketType); Output("- Address Familly : %d", protocolInfo.iAddressFamily); Output("- Byte Order : %d", protocolInfo.iNetworkByteOrder); Output("- Security Scheme : %d", protocolInfo.iSecurityScheme); Output("- Provider : %u", protocolInfo.ProviderId); Output("- Provider flags : "); OUTPROVIDER(PFL_MULTIPLE_PROTO_ENTRIES); OUTPROVIDER(PFL_RECOMMENDED_PROTO_ENTRY); OUTPROVIDER(PFL_HIDDEN); OUTPROVIDER(PFL_MATCHES_PROTOCOL_ZERO); Output("- Service flags : "); OUTSERVICES(XP1_CONNECTIONLESS); OUTSERVICES(XP1_GUARANTEED_DELIVERY); OUTSERVICES(XP1_GUARANTEED_ORDER); OUTSERVICES(XP1_MESSAGE_ORIENTED); OUTSERVICES(XP1_PSEUDO_STREAM); OUTSERVICES(XP1_GRACEFUL_CLOSE); OUTSERVICES(XP1_EXPEDITED_DATA); OUTSERVICES(XP1_CONNECT_DATA); OUTSERVICES(XP1_DISCONNECT_DATA); OUTSERVICES(XP1_INTERRUPT); OUTSERVICES(XP1_PSEUDO_STREAM); OUTSERVICES(XP1_SUPPORT_BROADCAST); OUTSERVICES(XP1_SUPPORT_MULTIPOINT); OUTSERVICES(XP1_MULTIPOINT_CONTROL_PLANE); OUTSERVICES(XP1_QOS_SUPPORTED); OUTSERVICES(XP1_UNI_SEND); OUTSERVICES(XP1_UNI_RECV); OUTSERVICES(XP1_IFS_HANDLES); OUTSERVICES(XP1_PARTIAL_MESSAGE); Output("----------------------------"); } } return true; } bool Connect(char* _ip, int _port) { CloseSocket(); strncpy(ip, _ip, 16); ip[15] = '\0'; port = _port; Output("starting client..."); sock = socket(AF_INET, SOCK_DGRAM, 0); if(sock == 0) { Output("failed to create socket."); CloseSocket(); return false; } Output("socket created."); if (!SetOptions(false, true, true, false, 16 * 1024)) { CloseSocket(); return false; } // bind socket to something (arbitrary port) SOCKADDR_IN my_address; int namelen = sizeof(my_address); my_address.sin_family = AF_INET; my_address.sin_port = htons(0); my_address.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (LPSOCKADDR)&my_address, sizeof(my_address)) == SOCKET_ERROR) { Output("failed to bind."); CloseSocket(); return false; } if(getsockname(sock, (sockaddr*) &my_address, &namelen) == SOCKET_ERROR) { Output("failed to get socket name."); CloseSocket(); return false; } if (namelen != sizeof(my_address)) { Output("error getting socket name."); CloseSocket(); return false; } Output("bound to %s:%d.", inet_ntoa(my_address.sin_addr), ntohs(my_address.sin_port)); // Setup the addr structure with the address information of what we are connecting to address.sin_family = AF_INET; address.sin_port = htons(port); address.sin_addr.s_addr = inet_addr(ip); SendCommand(CONNECT); return true; } bool SendCommand(int command) { if (sendto(sock, (const char*)&command, sizeof(command), 0, (LPSOCKADDR)&address, sizeof(address)) == SOCKET_ERROR) { Output("failed to send command %s command to %s:%d.", GetCommandName(command), inet_ntoa(address.sin_addr), ntohs(address.sin_port)); return false; } Output("command %s sent to %s:%d.", GetCommandName(command), inet_ntoa(address.sin_addr), ntohs(address.sin_port)); return true; } bool CloseSocket() { if(sock == 0) { return true; } Output("closing..."); shutdown(sock, SD_SEND); closesocket(sock); state = LIMBO; port = 0; sock = 0; ZeroMemory(ip, sizeof(ip)); ZeroMemory(&address, sizeof(address)); Output("closed."); return true; } bool Think(int iMS) { if(!ThinkSocket(iMS)) { return false; } return true; } bool ThinkSocket(int iMS) { if(sock == 0) { return false; } Output("thinking..."); fd_set read_sockets; timeval tv; tv.tv_sec = 0; tv.tv_usec = iMS; FD_ZERO(&read_sockets); FD_SET(sock, &read_sockets); int num_socks = select(1, &read_sockets, NULL, NULL, &tv); if(num_socks == SOCKET_ERROR) { Output("select() error"); CloseSocket(); return false; } if (FD_ISSET(sock, &read_sockets)) { int nbytes = recv(sock, buf, sizeof(buf), 0); if(nbytes == 0) { Output("connection closed by server"); CloseSocket(); return false; } if(nbytes < 0) { if(WSAGetLastError() == WSAECONNRESET) { Output("socket was reset"); } else { Output("critical error"); CloseSocket(); return false; } } else { Output("received data stream"); } } return true; } void Output(const char* format, ...) { va_list args; va_start(args, format); char* buff = new char[2048]; vsprintf(buff, format, args); printf("SOCK(%s)[%s] : %s\n", name, GetLastNetworkError(), buff); delete[] buff; } static bool SystemStartup() { printf ("SOCKET SYSTEM[%s] : starting network...\n", GetLastNetworkError()); const char* yes = "1"; WSADATA wsaData; int error = WSAStartup(NET_WINSOCK_VERSION, &wsaData); if(error) { printf ("SOCKET SYSTEM[%s] : failed to startup network\n", GetLastNetworkError()); return false; } printf ("SOCKET SYSTEM[%s] : network started\n", GetLastNetworkError()); return true; } static bool SystemCleanup() { printf ("SOCKET SYSTEM[%s] : shutting down network...\n", GetLastNetworkError()); WSACleanup(); printf ("SOCKET SYSTEM[%s] : network cleaned up\n", GetLastNetworkError()); return true; } static const char* GetCommandName(int command) { switch(command) { case CONNECT: return "CONNECT"; default: return "UNKNOWN"; } } static const char* GetLastNetworkError() { #define WSATOSTR(x) case (##x): return #x; int last_error = WSAGetLastError(); switch(last_error) { WSATOSTR(WSABASEERR) WSATOSTR(WSAEINTR) WSATOSTR(WSAEBADF) WSATOSTR(WSAEACCES) WSATOSTR(WSAEFAULT) WSATOSTR(WSAEINVAL) WSATOSTR(WSAEMFILE) WSATOSTR(WSAEWOULDBLOCK) WSATOSTR(WSAEINPROGRESS) WSATOSTR(WSAEALREADY) WSATOSTR(WSAENOTSOCK) WSATOSTR(WSAEDESTADDRREQ) WSATOSTR(WSAEMSGSIZE) WSATOSTR(WSAEPROTOTYPE) WSATOSTR(WSAENOPROTOOPT) WSATOSTR(WSAEPROTONOSUPPORT) WSATOSTR(WSAESOCKTNOSUPPORT) WSATOSTR(WSAEOPNOTSUPP) WSATOSTR(WSAEPFNOSUPPORT) WSATOSTR(WSAEAFNOSUPPORT) WSATOSTR(WSAEADDRINUSE) WSATOSTR(WSAEADDRNOTAVAIL) WSATOSTR(WSAENETDOWN) WSATOSTR(WSAENETUNREACH) WSATOSTR(WSAENETRESET) WSATOSTR(WSAECONNABORTED) WSATOSTR(WSAECONNRESET) WSATOSTR(WSAENOBUFS) WSATOSTR(WSAEISCONN) WSATOSTR(WSAENOTCONN) WSATOSTR(WSAESHUTDOWN) WSATOSTR(WSAETOOMANYREFS) WSATOSTR(WSAETIMEDOUT) WSATOSTR(WSAECONNREFUSED) WSATOSTR(WSAELOOP) WSATOSTR(WSAENAMETOOLONG) WSATOSTR(WSAEHOSTDOWN) WSATOSTR(WSAEHOSTUNREACH) WSATOSTR(WSAENOTEMPTY) WSATOSTR(WSAEPROCLIM) WSATOSTR(WSAEUSERS) WSATOSTR(WSAEDQUOT) WSATOSTR(WSAESTALE) WSATOSTR(WSAEREMOTE) WSATOSTR(WSASYSNOTREADY) WSATOSTR(WSAVERNOTSUPPORTED) WSATOSTR(WSANOTINITIALISED) WSATOSTR(WSAEDISCON) WSATOSTR(WSAENOMORE) WSATOSTR(WSAECANCELLED) WSATOSTR(WSAEINVALIDPROCTABLE) WSATOSTR(WSAEINVALIDPROVIDER) WSATOSTR(WSAEPROVIDERFAILEDINIT) WSATOSTR(WSASYSCALLFAILURE) WSATOSTR(WSASERVICE_NOT_FOUND) WSATOSTR(WSATYPE_NOT_FOUND) WSATOSTR(WSA_E_NO_MORE) WSATOSTR(WSA_E_CANCELLED) WSATOSTR(WSAEREFUSED) case 0: return "OK"; default: return "WSAEUNKNOWN"; } }private: char* name; SOCKET sock; SOCKADDR_IN address; int port; char ip[16]; char buf[1024]; NetLib_SendStream* sendstream; NetLib_RecvStream* recvstream; enum STATE { LIMBO=0, LISTENING, ACCEPTING, ESTABLISHED }; enum { CONNECT = 0 }; STATE state;};NetLib_Socket* pxClient;NetLib_Socket* pxServer;void main(int argc, char* argv[]){ printf ("starting application\n"); NetLib_Socket::SystemStartup(); pxServer = new NetLib_Socket("server"); pxClient = new NetLib_Socket("client"); pxServer->Listen(3000); pxClient->Connect("127.0.0.1", 3000); while (1) { if(!pxServer->Think(1000)) { break; } if(!pxClient->Think(1000)) { break; } Sleep(500); } delete pxClient; delete pxServer; NetLib_Socket::SystemCleanup(); printf ("application closed\n"); getch(); exit(0);}