Problems with winsock on Win7, not XP and Vista

Hello

I am working on a project which depends on winsock. I have based my code upon the Winsock guide on MSDN, the only difference should be that I have made a class out of it. On Windows XP and Vista the code runs fine, but on 7 i am getting this from my console:
Setting up conenction
Unable to connect to server!
send failed: 10093
Are the game started?
Waiting for server...
Waiting for server...
Waiting for server...
Waiting for server...
Waiting for server...

And here are the networking code:
comm.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "includes.h"
//#define _WIN32_WINNT 0x501
//#include <winsock2.h>
//#include <ws2tcpip.h>
#include "comm.h"
comm::comm(){
	int iResult;
	printf("Setting up conenction\n");
	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (iResult != 0) {
	    printf("WSAStartup failed: %d\n", iResult);
	    //return 1;
	}

	struct addrinfo *result = NULL,
                *ptr = NULL,
                hints;

	ZeroMemory( &hints, sizeof(hints) );
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	// Resolve the server address and port
	iResult = getaddrinfo(DEFAULT_HOST, DEFAULT_PORT, &hints, &result);
	if (iResult != 0) {	
		printf("getaddrinfo failed: %d\n", iResult);
	    WSACleanup();
	    //return 1;
	}

	//this->ConnectSocket = INVALID_SOCKET;
	// Attempt to connect to the first address returned by
	// the call to getaddrinfo
	ptr=result;
	
	// Create a SOCKET for connecting to server
	this->ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
	    ptr->ai_protocol);
	if (this->ConnectSocket == INVALID_SOCKET) {
		printf("Error at socket(): %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		WSACleanup();
	    //return 1;
	}

	// Connect to server.
	iResult = connect( this->ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
	if (iResult == SOCKET_ERROR) {
	    closesocket(this->ConnectSocket);
	    this->ConnectSocket = INVALID_SOCKET;
	}
	
	// Should really try the next address returned by getaddrinfo
	// if the connect call failed
	// But for this simple example we just free the resources
	// returned by getaddrinfo and print an error message
	
	freeaddrinfo(result);
	
	if (this->ConnectSocket == INVALID_SOCKET) {
	    printf("Unable to connect to server!\n");
	    WSACleanup();
	    //return 1;
	}


}
bool comm::write(char * msg){
	int iResult;

	iResult = send( this->ConnectSocket, msg, (int)strlen(msg), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(this->ConnectSocket);
        WSACleanup();
        return 1;
    }
	//printf("Sent:", msg);
		
	return true;
}

char comm::read(){
	int recvbuflen = DEFAULT_BUFLEN;

	//char sendbuf[] = "this is a test";
	//char recvbuf[DEFAULT_BUFLEN];
	return recv(this->ConnectSocket, this->recvbuf, recvbuflen, 0);
	//char returnVar = recvbuf;

}
void comm::shutdownSocket(){
	int iResult;
	iResult = shutdown(this->ConnectSocket, SD_SEND);
	if (iResult == SOCKET_ERROR) {
		printf("shutdown failed: %d\n", WSAGetLastError());
		closesocket(this->ConnectSocket);
		WSACleanup();
	}
}

comm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef COMM_H
#define COMM_H
//#include <winsock2.h>
//#include <ws2tcpip.h>
//#include <stdio.h>
#include "includes.h"


class comm{	
	public:
		comm();
		bool write(char *);
		void shutdownSocket();
		char read();
		char recvbuf[DEFAULT_BUFLEN];
		SOCKET ConnectSocket;
	private:
		WSADATA wsaData;
		
};


#endif 


includes.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//#ifndef INCLUDES_H
#define INCLUDES_H
//#define WINVER 0x0600
#include <iostream>

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include "comm.h"
#define DEFAULT_NAME "hakonvl_bot"
#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT "1986"
#define DEFAULT_BUFLEN 512

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
//#endif
using namespace std;

I now the comm::write() does not work. However, I cant see where the error are happening, even after reading the description of the errorcode on MSDN. The code should get most errors, but still it does not work.

And as I said the code compiles and runs just as expected on XP and Vista. I have tried both gcc from MinGW and Visual C++ Express 2010.

Thanks :)
Last edited on
1
2
3
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
What does connect() return?
closed account (3TXyhbRD)
Hi five, had this issue. Your problem comes from:

#define DEFAULT_HOST "localhost"

Win7 doesn't recognize "localhost". Instead of "localhost" type in your IP.
If you're willing to make a game with either .NET, OpenGL or DarkGDK, I advise you check exactly what recv() does (not necessarily what it returns), there's a catch.
kbw: Connect() returns SOCKET_ERROR, and WSAGetLastError gives me the code 10093 which means

Successful WSAStartup not yet performed.

Either the application has not called WSAStartup or WSAStartup failed. The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks), or WSACleanup has been called too many times.


recv reads information from the socket, and return the number of bytes read from the socket. The reason that my wrapper don't work was that I messed with some pointers and char arrays, there is a pretty long time since I used C++ last time. And since I have a pretty small amount of time to finish this I did not take me time to check how I actually are going to do it. And it is not a game, is is a kind of a game bot to a competition here at The Gathering :p

I will try to change the DEFAULT_HOST to the IP address, but first I have to make the code compile. I have worked on something else, which apparently have broken the code.

Thanks btw :)
That's interesting, localhost is commented out in C:\WINDOWS\system32\drivers\etc\hosts

It's just a matter of uncommenting that line.

type in your IP
The loop back adapter (127.0.0.x) is different from your network or internet address.
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host

# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost

Why is it like this? It is ok that the resolution is handled by DNS, but I still thinks that this is kind of weird. And then I guess it is like this on other machines running 7 to, so I guess I have to find a way to do a DNS lookup getaddrinfo only looks in the hosts file? I cant find anything about how getaddrinfo looks up the hostname on MSDN though.

And how did you now this? I did not think about checking this at all, and I have spent some time om this error.

Edit: It did not solve the error, still not connecting and same error code.

I am not sure how important this is, since I can just implement DNS or I can just live with typing the IP. It should always be 127.0.0.1 anway.
Last edited on
On Unix, the redirector determines the lookup location and order.

I believe that on Windows, hosts takes precidence over WINS or DNS. It looks like lmhosts can be switched off in the network config section.

The whole point of supporting localhost is so that client and server software can be run on the same box.

It's probably considered a security issue, I can sort of see why.

EDIT: Why do you call WSAStartup twice?
Last edited on
closed account (3TXyhbRD)
recv reads information from the socket, and return the number of bytes read from the socket. The reason that my wrapper don't work was that I messed with some pointers and char arrays, there is a pretty long time since I used C++ last time. And since I have a pretty small amount of time to finish this I did not take me time to check how I actually are going to do it. And it is not a game, is is a kind of a game bot to a competition here at The Gathering :p

And it blocks the program until you actually receive something (including the error or disconnect). It's good to use recv() directly when you want to intentionally block the program. To solve this issue check select() and also note what it does the the fd_set array(s). It's really a pain in the bucket.
LilJoje: I know that, but since this is a one threaded console application I dont really see the point. If I can't get anything out of the socket the program will be useless.

Kbw: Ok, but it seems a bit strange that the official docs on MSDN tells me to do it. I and where do I call WSAStartup other than on line 8 in comm.cpp? I can't find it anywhere.
closed account (3TXyhbRD)
LilJoje: I know that, but since this is a one threaded console application I dont really see the point. If I can't get anything out of the socket the program will be useless.

Just saying :p
And if you don't mind or Kbw, you have one call of WSAStartup() at line 9 and another at 12.
Oh, it was commented in my code so I didn't see it here.

Thanks for the help anyway :)
closed account (3TXyhbRD)
Kbw is the one who noticed the double function call. I just did the "localhost" one, partially ;)
Topic archived. No new replies allowed.