# problem using threads with winsock2

This topic is 3844 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I don't know if it is against the forum's rules, i kind have maked a similar thread already, but it is a realy annoying problem, and i can't solve it by myself. So... I am working on a Class to encapsulate the winsock2 API, I'm trying to create a class similar to MFC's CAsyncSocket class, but using threads instead of windows messages. The entire Class(some variables and comments are in portuguese)
#include <iostream>
#include "circ.h"//include all others .h files

CSocket::CSocket()
{
lasterror=0;
host2=NULL;
FD_ZERO(&set);
time.tv_sec=0;
time.tv_usec=0;

}
CSocket::~CSocket()
{
//dtor
}
int CSocket::Create()
{
//CRIA UM CLIENT

//inicializa a utilização de sockets (versão 2,2)
int error = WSAStartup (MAKEWORD(2,2), &w);
if (error!=0) //se houver erro
{
lasterror= WSAGetLastError();
return error;
}

s=socket(AF_INET,SOCK_STREAM,0); //cria um socket sem porta  tcp/ip

if (s==INVALID_SOCKET) //se s é um socket invalido
{
lasterror= WSAGetLastError(); //captura o erro
WSACleanup ();
return SOCKET_ERROR;
}
FD_SET(s,&set);
return 0;

}
int CSocket::Create(unsigned int porta)
{

//CRIA UM SERVER

int error1 = WSAStartup (MAKEWORD(2,2), &w); //inicializa a utilização de sockets(verção 2,2)
if (error1!=0)
{
lasterror= WSAGetLastError();
return error1; //se der erro, retorna o erro
}

s=socket(AF_INET,SOCK_STREAM,0); //cria um socket sem porta  tcp/ip
if (s==INVALID_SOCKET)
{
lasterror=WSAGetLastError();
WSACleanup ();
return SOCKET_ERROR;
}

int error2;
sockaddr_in addr;//estrutura que guarda os endereços tcp/ip

addr.sin_family=AF_INET; // familia da internet
addr.sin_port=porta; // Designa a porta

if (error2==SOCKET_ERROR)
{
lasterror = WSAGetLastError(); //captura o erro
WSACleanup ();
return error2; //retorna o erro
}

FD_SET(s,&set);
return 0;
}

int CSocket::Connect(char* host, unsigned int porta)
{
//COnecta tanto ip quanto hostname

HOSTENT *hostinfo; //estrutura que guarda informações do host
host2=host;
hostinfo = gethostbyname(host);

if (hostinfo==NULL)
{
lasterror= WSAGetLastError(); //captura o erro
return HOSTNAMEERROR; // retorna erro do host
}

SOCKADDR_IN target; //estrutura que vai guradar as informações para conexão, ip...

target.sin_family=AF_INET; //família da internet
target.sin_port=htons(porta); //atribuindo uma porta para conexão

{

lasterror= WSAGetLastError();//caprutura o erro
return SOCKET_ERROR;//returna erro
}

OnConnect(); //chama o evento ao se conectar
return 0; //returna tudo OK

}
int CSocket::Send(const char*buf, int size)
{

//Envia

if (send (s, buf, size,0)==SOCKET_ERROR)
{
lasterror=WSAGetLastError();//captura o erro
return SOCKET_ERROR; //retorna erro
}
return 0; //retorna tudo OK

}

int CSocket::Listen(CSocket* Socket,int maxconn )
{
if (listen(Socket->s,maxconn)==SOCKET_ERROR)
{
lasterror=WSAGetLastError();
return SOCKET_ERROR;
}
return 0;
}

int CSocket::Receive(char* buf, int size)
{
//inconlopeta

if (recv (s, buf, size, 0)==SOCKET_ERROR)
{
lasterror=WSAGetLastError();
return SOCKET_ERROR;
}
return 0;
}

void CSocket::OnConnect()
{

}
{
char buffer[512];
std::cout<<buffer<<std::endl;
}

void CSocket::OnSend()
{
}

void CSocket::OnClose()
{
}
int CSocket::GetLastError()
{
return lasterror;
}

char * CSocket::GetHost()
{
return host2;
}

void CSocket::loop(void* parameter)
{

CSocket *obj=reinterpret_cast<CSocket*>(parameter);
int teste2;
while(1==1)
{
teste2=select(0,&(obj->set),NULL,NULL,&(obj->time));
if (teste2==SOCKET_ERROR)
{
obj->lasterror=WSAGetLastError();
std::cout<<teste2<<std::endl;
std::cout<<obj->lasterror<<std::endl;

}
else
{
std::cout<<teste2<<std::endl;

}
}

}


When i test it with this line teste2=select(0,&(obj->set),NULL,NULL,&(obj->time));checking for readability, it dont work and returns... "WSAEINVAL 10022 Invalid argument. Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket—for instance, calling accept on a socket that is not listening." from msdn. but when a use this line instead, select(0,NULL,&(obj->set),NULL,&(obj->time)); checking for writability, select returns 1, like it should. So, i assume that my parameters passed to select are not the problem, but something else is wrong, something i can't figure out. i know there is something to be read becouse when i just read without use select i've receive the irc serve info. someone please, give me a hand.

##### Share on other sites
Quote:
 I'm trying to create a class similar to MFC's CAsyncSocket class

Why?

Anyway...

The socket creation:
s=socket(AF_INET,SOCK_STREAM,0);
should be ... , IPPROTO_TCP);

The following
if (connect(s,(SOCKADDR*)(&target),sizeof(target))==SOCKET_ERROR)
should probably be
... == INVALID_SOCKET

You have also lots of confusion about who does what, with WSAStartup and socket creation over several methods, when they could all be in single constructor. But I don't know if this is the problem, since you don't show how you actually create the socket, so I can only assume you're doing it the right way.

##### Share on other sites
Well, I've tryed what you said and, as you predicted, it doesn't work. The funny thing is; in the first iteration of my infinit while loop, select returns 0, instead SOCKET_ERROR, but, after that, returns the old friends -1 10022.It must have something to do about the error. And happens just when asking for readability, every other select returns what it should.

Thanks anyway. Any other ideas?

##### Share on other sites
Ahh, another thing, i'm creating the socket correctly, it does everything, receives, sends,all that, but not in a thread like i want.

##### Share on other sites
I very strongly suggest that you read the documentation for every function you are using carefully; there are a lot of minor problems with your code which, unfortunately, I don't really have time to get into at the moment.

For your immediate problem, see MSDN on select(), which indicates that the error code WSAEINVAL means that your timeout parameter is invalid for some reason. Try checking the timeout to make sure it is sane, or just pass a 0 timeout so the function returns immediately with the results (which is probably what you should do anyways).

As far as threading - I'm not sure from your code what you're expecting to happen here, or how you're determining that it doesn't do what you want. Do you have experience writing multithreaded code? Why did you choose to use threads for this instead of more typical approaches for writing sockets code? What specific issues, if any, did you encounter that made you want to write an asynchronous socket class?

(I ask because, typically, wanting such a class is a classic beginner mistake from someone who hasn't quite understood how sockets work. Don't worry, though; sockets are complicated and not really intuitive, so you're hardly alone.)

Just a few quick things - this is by no means everything that needs work in your code:

• Every call to WSAStartup should have a matching call to WSACleanup, as noted in the documentation. Also, it's extremely rare that you need to call it more than once, so calling it just in main() or whatever should be fine.

• Why have a destructor if it doesn't do anything? (Unless you're doing something with virtual inheritance which you didn't post, in which case you can ignore me [wink]

• I'd recommend using RAII instead of having a separate Create function; in this case having the destructor close the socket is the logical arrangement. If you aren't familiar with C++'s RAII idiom, I highly recommend that you read up on it a bit.

• Be aware that when you receive an incoming connection on a socket, the original listening socket isn't the same one that accepts the connection; see the documentation on listen and accept for details.

Lastly, there are some very good resources mentioned in the forum FAQ, which I highly recommend you check out for further reading.

##### Share on other sites
THANKS, THANKS, THANKS....

Now it's working fine. The problem was with the timeval{0,0}structure, when I replace it with a zero, everything gos OK. THANKS again!!!

##### Share on other sites
timeval{0,0} is a valid value. It means "test and immediately return." If you just pass 0 (NULL), it means "block until something interesting happens." Very different meanings. However, if you're inside a thread, then blocking might be just fine.

##### Share on other sites
I've figure out the problem, the timeval structure must be a const timeval. But blocking select is better using threads as you said.

##### Share on other sites
Quote:
 the timeval structure must be a const timeval

That has nothing to do with it. A timeval * will be converted to a timeval const * by the compiler.

It seems to me that your code previously didn't work the way you expected, and now it does. However, it also seems to me that you don't know why that's actually the case. That, in turn, indicates that you are probably in a little bit over your head, and probably should spend some time learning more about your tools (language/compiler/library) before you advance into concepts like multi-threaded distributed programming.

1. 1
2. 2
Rutin
21
3. 3
JoeJ
18
4. 4
5. 5
gaxio
12

• 14
• 40
• 23
• 13
• 13
• ### Forum Statistics

• Total Topics
631724
• Total Posts
3001897
×