|
-
December 16th, 2008, 10:14 PM
#1
Is this how you use select()?
I found out how to use the select() function, or at least I think I have. It allows the loop to keep going and then receive something when there is something to receive.
Here's the Server:
Code:
// main.cpp
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define SOCKET int
#endif
#ifdef WIN32
#include <winsock2.h>
#include <iostream>
#include <io.h>
#pragma comment (lib,"ws2_32")
#endif
int main()
{
WORD SocketVersion;
WSADATA WsaData;
int WsaErr;
int recvBytes(0);
char Buffer[5000];
bool InternalError(false);
bool ActiveAccept(true);
bool ActiveApp(true);
char* ip_address = NULL;
fd_set FD_SET1;
struct timeval timeOUT;
timeOUT.tv_sec = 0;
timeOUT.tv_usec = 0;
FD_ZERO (&FD_SET1);
SocketVersion = MAKEWORD(2, 2);
WsaErr = WSAStartup(SocketVersion, &WsaData);
std::cout << "\n";
if(WsaErr == 0)
{
if(LOBYTE(WsaData.wVersion) == 2 || HIBYTE(WsaData.wVersion) == 2)
{
SOCKET My_Socket;
My_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(My_Socket != INVALID_SOCKET)
{
sockaddr_in Server;
Server.sin_family = AF_INET;
Server.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);
Server.sin_port = htons(55555);
if(bind(My_Socket, (SOCKADDR*)&Server, sizeof(Server)) != SOCKET_ERROR)
{
if(listen(My_Socket, 1) != SOCKET_ERROR)
{
SOCKET AcceptConnection;
AcceptConnection = SOCKET_ERROR;
std::cout << " Server: The Server Has Been Started Up Successfully!\n";
while(ActiveAccept == true)
{
AcceptConnection = accept(My_Socket, NULL, NULL);
if(AcceptConnection != SOCKET_ERROR)
{
ActiveAccept = false;
}
}
int ClientConnected = 1;
My_Socket = AcceptConnection;
//######## MAIN LOOP
while(ActiveApp == true)
{
FD_ZERO(&FD_SET1);
FD_SET(My_Socket, &FD_SET1);
if(ClientConnected == 1)
{
std::cout << " Server: Client Connected!\n";
ClientConnected = 0;
}
//######## START SEND RECEIVE HERE
if(select((int)My_Socket, &FD_SET1, 0, 0, &timeOUT))
{
recvBytes = recv(My_Socket, Buffer, 5000, 0);
if(recvBytes != SOCKET_ERROR)
{
std::cout << " Server->Message: " << Buffer << "\n";
}
else
{
if(WSAGetLastError() == 10054)
{
std::cout << " Server: Client Disconnected.\n";
ActiveApp = false;
InternalError = true;
}
}
}
}
}
else
{
std::cout << " Server: " << WSAGetLastError() << "\n";
InternalError = true;
}
}
else
{
std::cout << " Server: " << WSAGetLastError() << "\n";
InternalError = true;
}
}
else
{
std::cout << " Server: " << WSAGetLastError() << "\n";
InternalError = true;
}
}
else
{
std::cout << " Server: The DLL in use does not support this version of WinSock!\n";
InternalError = true;
}
}
else
{
std::cout << " Server: There was an error starting WinSock!\n";
InternalError = true;
}
// Internal Error Loop
if(InternalError == true)
{
for(int InternErr = 0;InternErr < 3;InternErr++)
{
if(InternErr == 1)
{
std::cout << "\n Closing...\n";
}
Sleep(1000);
}
}
}
Client:
Code:
// main.cpp
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define SOCKET int
#endif
#ifdef WIN32
#include <winsock2.h>
#include <iostream>
#include <string>
#pragma comment (lib,"ws2_32")
#endif
int main()
{
WSADATA WsaData;
WORD SocketVersion;
int SocketCreate;
bool InternalError(false);
SocketVersion = MAKEWORD(2, 2);
SocketCreate = WSAStartup(SocketVersion, &WsaData);
std::cout << "\n";
if(SocketCreate == NO_ERROR)
{
SOCKET My_Socket;
My_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(My_Socket != INVALID_SOCKET)
{
sockaddr_in Client;
Client.sin_family = AF_INET;
Client.sin_addr.s_addr = inet_addr("127.0.0.1");
Client.sin_port = htons(55555);
if(connect(My_Socket, (SOCKADDR*)&Client, sizeof(Client)) != SOCKET_ERROR)
{
//######## MAIN LOOP
while(1)
{
//######## START SEND RECEIVE HERE
static std::string Message;
std::cout << " Client->Type A Message To Send To Server: ";
getline(std::cin, Message);
if(Message != "")
{
if(send(My_Socket, Message.c_str(), 5000, 0) != SOCKET_ERROR)
{
std::cout << " Client: Message Sent!!!\n";
Message = "";
}
}
}
}
else
{
std::cout << " Client: Faild To Connect To Server!!!\n";
InternalError = true;
}
}
else
{
std::cout << " Client: " << WSAGetLastError() << "\n";
InternalError = true;
}
}
else
{
std::cout << " Client: There was an error on WSAStartup()!!!\n";
InternalError = true;
}
// Internal Error Loop
if(InternalError == true)
{
for(int InternErr = 0;InternErr < 3;InternErr++)
{
if(InternErr == 1)
{
std::cout << "\n Closing...\n";
}
Sleep(1000);
}
}
}
Everything seems to go fine if I connect to the server though my local ip address.
But when I connect though my public IP address things go weird.
I can connect and everything. The problem is that when I send some data it also sends some other data, which seems to be null. This does not happen when I connect though 127.0.0.1.
And it does not happen if I remove select() regardless of the IP.
Like if I send the string "Hello World!" without the select function I will get:
Code:
Server->Message: Hello World!
With the select function I will get:
Code:
Server->Message: Hello World!
Server->Message:
Server->Message:
Or:
Code:
Server->Message: Hello World!
Server->Message:
The amount of "Null"s change. Sometimes there's 3, then maybe 2, 4 etc.
This is really annoying me because I have no idea whats causing this.
Thanks for any help that I may get!
-
December 17th, 2008, 12:37 PM
#2
Re: Is this how you use select()?
assuming you're using Windows, the first parameter of select should be 0 because on Windows, it is ignored.
Then, you should not call recv() on MySocket, because that is the server socket used for establishing connections.
You don't need
while(ActiveAccept == true)
because accept() will block unless you have set your server socket to nonblocking (which you don't have, as far as I can see.
You should put AcceptConnection into FD_SET1 and when select returns, first check the error condition (as you do), then test with FD_ISSET if your socket is ready for reading (select can handle more than 1 socket).
And as you set your timeout to 0, select() might return immediately (I'm not sure). If you want to wait forever, pass 0 as last parameter.
HTH,
Richard
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|