same-machine client-server connection. 127.0.0.1?

Started by
3 comments, last by oliii 18 years, 4 months ago
I'm trying a small app, to connect a client to a server, and using the address 127.0.0.1:2000. The client and server run up to the connection attempts, but then, they dont seem to see each other. I have two simple test applications. maybe someone knows what's wrong. Note that I want to use the select() mechanism. Not the WSAASyncSelect() stuff. Maybe there is something obvious I've missed. I don't run a DHCP server, so I don;t have a 192.168.0.x type of address. My client is a datagram socket, dunno if that's a problem. client

#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")

SOCKET client_socket = 0;
SOCKADDR_IN	client_address;
int listen_port = 2000;
char ip[] = "127.0.0.1";

void main(int argc, char* argv[])
{
	const char* yes = "1";
	WSADATA wsaData;
    int error = WSAStartup(NET_WINSOCK_VERSION, &wsaData);

	if(error)
	{
		printf ("failed to startup network\n");
		goto exit;
	}
	printf ("network started\n");
	
	ZeroMemory(&client_address, sizeof(client_address));

	printf ("Starting client...\n");
	
	client_socket = socket(AF_INET, SOCK_STREAM, 0);
	
	if(client_socket == 0)
	{
		printf ("net : failed to create socket.\n");
		goto exit;
	}
	printf ("net : socket created.\n");

	// Setup the addr structure with the address information of what we are connecting to
	client_address.sin_family		= AF_INET;
	client_address.sin_port			= htons(listen_port);
	client_address.sin_addr.s_addr	= inet_addr(ip);
	
	// Connect the socket
	if(connect(client_socket, (LPSOCKADDR)&client_address, sizeof(client_address)) == SOCKET_ERROR)
	{
		printf ("net : failed to connect.\n");
		goto exit;
	}
	printf ("net : connecting to %s:%d.\n", inet_ntoa(client_address.sin_addr), listen_port);

	while (1)
	{
		Sleep(30);

		fd_set read_sockets;
	
		timeval tv;
		tv.tv_sec = 0;
		tv.tv_usec = 1;

		FD_ZERO(&read_sockets);
		FD_SET(client_socket, &read_sockets);
		
		select(1, &read_sockets, NULL, NULL, &tv);

		if (FD_ISSET(client_socket, &read_sockets))
		{
			char buf[2048];
			int nbytes = recv(client_socket, buf, sizeof(buf), 0);

			if(nbytes == 0)
			{
				printf("net : connection closed by server\n");
				goto exit;
			}

			if(nbytes < 0)
			{
				printf("net : connection error\n");
				goto exit;
			}

			else
			{
				printf("net : received data\n");
			}
		}
	}

exit:

	shutdown(client_socket, SD_SEND);
	closesocket(client_socket);
	client_socket = 0;

	WSACleanup();
	printf ("game closed\n");

	getch();
	exit(0);
}



server

#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")

SOCKET listen_socket = 0;
SOCKET client_socket = 0;
SOCKADDR_IN	listen_address;
SOCKADDR_IN	client_address;
int listen_port = 2000;
char ip[] = "127.0.0.1";

void main(int argc, char* argv[])
{
	const char* yes = "1";
	WSADATA wsaData;
    int error = WSAStartup(NET_WINSOCK_VERSION, &wsaData);

	if(error)
	{
		printf ("failed to startup network\n");
		goto exit;
	}
	printf ("network started\n");
	
	ZeroMemory(&client_address, sizeof(client_address));
	ZeroMemory(&listen_address, sizeof(listen_address));

	printf ("Starting server...\n");

	listen_socket = socket(AF_INET, SOCK_STREAM, 0);

	if(listen_socket == 0)
	{
		printf ("listen : failed to create socket.\n");
		goto exit;
	}
	printf ("listen : socket created.\n");

	listen_address.sin_family		= AF_INET;
	listen_address.sin_port			= htons(listen_port);
	listen_address.sin_addr.s_addr	= htonl(INADDR_ANY);

	if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, yes, sizeof(int)) == SOCKET_ERROR) 
	{
		printf ("listen : failed to set socket options.\n");
		goto exit;
	}
	printf ("listen : socket opotions set.\n");
		
	if(bind(listen_socket, (LPSOCKADDR)&listen_address, sizeof(listen_address)) == SOCKET_ERROR)
	{
		printf ("listen : failed to bind.\n");
		goto exit;
	}
	printf ("listen : bind successful.\n");
	
	if(listen(listen_socket, 16) == SOCKET_ERROR)
	{
		printf ("listen : failed to listen.\n");
		goto exit;
	}
	printf ("listen : waiting for connection.\n");

	while (1)
	{
		Sleep(30);

		fd_set read_sockets;
	
		timeval tv;
		tv.tv_sec = 0;
		tv.tv_usec = 1;

		FD_ZERO(&read_sockets);
		FD_SET(listen_socket, &read_sockets);
		
		select(1, &read_sockets, NULL, NULL, &tv);

		if (FD_ISSET(listen_socket, &read_sockets))
		{
			int addrsize = sizeof(client_address);

			// Take the connection from the listening socket, "serversock"
			client_socket = accept(listen_socket, (sockaddr*) &client_address, &addrsize);
			printf("listen : new connection from %s on socket %d\n", inet_ntoa(client_address.sin_addr), client_socket);
			goto exit;
		}
	}

exit:

	shutdown(listen_socket, SD_SEND);
	shutdown(client_socket, SD_SEND);
	closesocket(listen_socket);
	closesocket(client_socket);
    listen_socket = 0;
	client_socket = 0;
	WSACleanup();
	printf ("game closed\n");

	getch();
	exit(0);
}



Everything is better with Metal.

Advertisement
a-ha.

I'm using a stream (tcp ip) socket on client, and it seems to work. what gives?

Everything is better with Metal.

OK, now I think I get it. can't use connect / accept with UDP socket. You have to create your own connection protocols. Is that it? [grin]

Everything is better with Metal.

your correct. UDP datagram is a "conectionless protocol". Beside the whole connect thing, realize that UDP accumulates data differently than TCP. in UDP you receive actual packets in chunks, while in TCP you recive them in a stream (like reading a file). This TCP stream can contain less or more than was sent by the client app. Then the last thing is the one you probably know, UDP is unreliable delivery while TCP was invented for realiable communication (hence the connect/disconnect).

As an aside - I had weird UDP problems when using the callback address, like the last data sent before a client quit would remain in the callback loop, for each server receive (infinately, until server quit as well). This however was never a problem with two seperate computers. Just a heads up (TCP was fine).
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);}

Everything is better with Metal.

This topic is closed to new replies.

Advertisement