Winsock threading problem!

Hi. I think i found a bug in VS2005 (or in the libraries for VC++).
I tried to create a socket and connect it (to let's say to a webserver) and create a new thread to handle all the incoming data. In the new thread I call recv on the socket and that thread is blocked (as it should since a webserver don't send any data before it's got a request. The problem is that if i now call send on the same socket from the main thread, it's blocking too and the program has frozen. Why is this happening? If i don't call recv on the socket, then send is returning instantly, as it should.

To complicate things a little bit more I have tried my test application (see below) compiled by VS2005 on several computers and it's the same bug everywhere. But a friend compiled the same code in VC++6 and that application does not freeze, not even on my computer. I run Windows 2000 by the way. Any suggestions what to do? Or is this a confirmed bug?

// Floaf

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <iostream>

DWORD WINAPI RecvThread(void *Data);
int main()
{
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2,2), &WSAData) != 0)
return false;

Sleep(100);
SOCKET ClientSocket = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, NULL);
if (ClientSocket != INVALID_SOCKET)
{
sockaddr_in sin_addr2;
sin_addr2.sin_family = AF_INET;
char Address[256];
int Port;
std::cout << "Enter address:" << std::endl;
std::cin >> Address;
std::cout << "Enter port:" << std::endl;
std::cin >> Port;
sin_addr2.sin_port = htons(Port);
sin_addr2.sin_addr.s_addr = inet_addr(Address);
int len = sizeof (sin_addr2);
if (connect(ClientSocket, (sockaddr *)&sin_addr2, len) != SOCKET_ERROR)
{
DWORD RecvThreadID;
HANDLE RecvThreadHandle = CreateThread(NULL, 0, RecvThread, (LPVOID)ClientSocket, 0,&RecvThreadID);
if (!RecvThreadHandle)
return 0;

Sleep(1000);
int result = send(ClientSocket, "testing", 7, NULL);
// Never reaches this point!!

}
}

return 0;
}

DWORD WINAPI RecvThread(void *Data)
{
SOCKET ClientSocket = (SOCKET)Data;
BYTE RecieveBuffer[65536];
int Recieved = recv(ClientSocket, (char*)RecieveBuffer, 5, NULL);
return 0;
}

[2650 byte] By [Floaf] at [2007-12-25]
# 1

I don't believe Winsock is guaranteeing any kind of thread safety, so you cannot simply assume that simultaneous operations on the same socket handle will work. You are much better off considering the alternatives, such as overlapped io, io completion ports, async callbacks through window messages or plain old polling.

einaros at 2007-9-3 > top of Msdn Tech,Visual C++,Visual C++ General...
# 2
I have searched for thread safety using winsock and I cant find any good answer. The only thing I have found is that if you send on the same socket at the same time, you dont know which message will be transmitted first.
But since recv is blocking, that funktion is intended to run on a different thread, or should at least be able to.
The only reason for send to block is that if the send buffer is full, which isn't the case here.
And why is it working if compiled with an older compiler? I would at least want an error or something, please :-)
I did use WSAAsyncSelect to run everything on a single thread before, but since I have a dual CPU setup I thought using a separate thread for sending and recieveing would be faster.
Floaf at 2007-9-3 > top of Msdn Tech,Visual C++,Visual C++ General...
# 3

The fact that it is blocking doesn't mean that two thread can safely access the same socket. Also, "Working" is somewhat of a vague term. It can be a mere timing issue, or perhaps library related. The point is that AFAIK, Winsock makes no claim on being thread safe, and you should therefore not assume that it is. Even if it happens to be in one version of the stack, it may not be in another version, thus breaking your application.

There are other aspects to your problem, though. Certain services, such as bandwidth monitors, firewalls and antivirus applications have been known to include faulty LSPs (Layered Service Providers). Given the proper timing, and faulty code, this can cause corrupted data, or access violations. As a test, try disabling all third party firewall application, AV and so forth.

A bit more on the socket matter can be found here:

Optimization on two+ CPUs, or even multicore, is another subject altogether. In either case, your NIC or harddrive is far more likely to be the bottleneck, not one thread on one core. As such, I can't see any immediate need for optimization.

In the future, please direct such questions to the http://msdn.microsoft.com/newsgroups/default.aspx?dg=microsoft.public.win32.programmer.networks&lang=en&cr=US newsgroup. You are far more likely to get the wanted attention there.

einaros at 2007-9-3 > top of Msdn Tech,Visual C++,Visual C++ General...
# 4
Thanks for your answers and for the links!
I see that others are having quite different experience of this issue, and as you say, Microsoft does not say that winsock is thread safe. Lets hope that they add the information that it's not thread safe to msdn so these things don't happen again.

I did try this compiled code on quite a few different computers with both win2000 and XP and it's the same problem. This is why i think the library (ws2_32.lib, not the ws2_32.dll) is the part that is causing the problem. But reading about all the different problems others did have, I'm going for one thread again :-)
If there is a chance that the code I'm writing will not work in 100% of the cases, then I have to to it another way.

Thanks again!

Floaf at 2007-9-3 > top of Msdn Tech,Visual C++,Visual C++ General...