I am creating a socket. It works first time easily then i stop the socket and regenerate it gives me error
class MainServer{
private:
SOCKET soo;
public:
// I have Basically Created Server Socket in this Function
// And passed it
SOCKET socket_control_mob(){
struct sockaddr_in server;
WSADATA wsa;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
MessageBox(NULL, TEXT("Failed"), L"Failed", NULL);
soo = NULL;
return soo;
}
printf("Initialised.\n");
//MessageBox(NULL, TEXT("Initialised"), L"Simple Message", NULL);
//Create a socket
if ((soo = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
MessageBox(NULL, TEXT("Socket Not Created1"), L"Failed", NULL);
soo = NULL;
return soo;
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8890);
//Bind
if (bind(soo, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
MessageBox(NULL, TEXT("Binding Error"), L"Failed", NULL);
soo = NULL;
return soo;
}
puts("Bind done");
//MessageBox(NULL, TEXT("Bind Done"), L"Simple Message", NULL);
return soo;
}
bool server_close_socket(){
closesocket(soo);
WSACleanup();
return true;
}
};
I have created a socket by calling
MainServer s;
s.socket_control_mob()
I have stopped socket by
s.server_close_socket()
Socket does not create after stopping it
You are mishandling the socket, and even the WinSock library itself. Try something more like this instead:
class MainServer
{
private:
SOCKET soo;
bool init;
public:
MainServer()
: soo(INVALID_SOCKET), init(false)
{
WSADATA wsa;
printf("\nInitialising Winsock...");
int err = WSAStartup(MAKEWORD(2, 2), &wsa);
if (err != 0)
{
printf("Failed. Error Code : %d\n", err);
MessageBox(NULL, L"WSAStartup Failed", L"Failed", NULL);
}
else
{
init = true;
printf("Initialized.\n");
//MessageBox(NULL, L"Initialized", L"Simple Message", NULL);
}
}
~MainServer()
{
close_server_socket();
if (init)
WSACleanup();
}
SOCKET socket_control_mob()
{
struct sockaddr_in server = {0};
close_server_socket();
//Create a socket
soo = socket(AF_INET, SOCK_STREAM, 0);
if (soo == INVALID_SOCKET)
{
printf("Could not create socket. Error Code : %d\n", WSAGetLastError());
MessageBox(NULL, L"Socket Not Created", L"socket Failed", NULL);
return INVALID_SOCKET;
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8890);
//Bind
if (bind(soo, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed. Error Code : %d", WSAGetLastError());
MessageBox(NULL, L"Binding Error", L"bind Failed", NULL);
close_server_socket();
return INVALID_SOCKET;
}
printf("Bind done.\n");
//MessageBox(NULL, L"Bind Done", L"Simple Message", NULL);
return soo;
}
void server_close_socket()
{
if (soo != INVALID_SOCKET)
{
closesocket(soo);
soo = INVALID_SOCKET;
}
}
};
This is a well-known thing. Your created socket is in FIN_WAIT state. To avoid the problem, wait for 2 minutes before re-running the program, follow 'graceful shutdown' protocol or provide SO_REUSEADDR option for the socket.
Related
when I compile this program and run it, I get the output below. I added the bind failed with error output for debugging and it suggests that with the error code that I received from listen the socket is not bound using bind but the 0 output is confusing me as that is the output when everything worked. I would appreciate any suggestions
#define DefaultBufLen 1024
SOCKET Socket = INVALID_SOCKET;
int difficulty = 0;
WSADATA wsaData;
struct addrinfo* result = NULL,
* ptr = NULL,
hints;
sockaddr_in Service;
int recvbuflen = DefaultBufLen;
char SendBuf[DefaultBufLen] = "";
char RecvBuf[DefaultBufLen] = "";
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
wprintf(L"Startup failed with error code %d\n", WSAGetLastError());
return 1;
};
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Socket == INVALID_SOCKET) {
wprintf(L"Socket failed with error: %1d\n", WSAGetLastError());
WSACleanup();
return 1;
};
Service.sin_family = AF_INET;
Service.sin_addr.s_addr = inet_addr("127.0.0.1");
Service.sin_port = htons(27015);
bind(Socket, (SOCKADDR*)&Service, sizeof(Service));
wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
while (1) {
if (listen(Socket, 2000) == SOCKET_ERROR) {
wprintf(L"listen failed with error: %ld\n", WSAGetLastError());
closesocket(Socket);
WSACleanup();
return 1;
}
else {
wprintf(L"listen succeeded!\n");
}
SOCKET AcceptingSocket;
wprintf(L"Waiting for client to connect...\n");
AcceptingSocket = accept(Socket, NULL, NULL);
if (AcceptingSocket == INVALID_SOCKET) {
wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
closesocket(Socket);
WSACleanup();
return 1;
}
else {
wprintf(L"Client connected.\n");
}
int Error = 0;
do {
Error = recv(Socket, RecvBuf, recvbuflen, 0);
if (Error > 0)
printf("Bytes received: %d\n", Error);
else if (Error == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (Error > 0);
string TranslatedRecvBuf = RecvBuf;
vector<string> Request;
boost::split(Request, TranslatedRecvBuf, boost::is_any_of(";"));
if (Request[0] == "RBlock") {
Irrelevant
else if (Request[0] == "DBlock") {
Irrelevant
else if (Request[0] == "TxIncl") {
Irrelevant
else if (Request[0] == "BaLook") {
Irrelevant
closesocket(AcceptingSocket);
};
};
Output:
bind failed with error: 0
listen failed with error: 10022
[process exited with code 1 (0x00000001)]
#define PORT 3000
int sock()
{
int valread;
struct sockaddr_in serv_addr;
const char* hello = "Hello from client";
char buffer[1024] = { 0 };
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
send(sock, hello, strlen(hello), 0);
printf("Hello message sent\n");
return 0;
}
I have this code for the sockets, to be sent at localhost:3000 address. But they are not sent, and Connection failed error pops up. I have node.js server listener socket open at that port.
On Windows only 1, you must call WSAStartup() to initialize the Winsock library before using any other socket functions, like connect(). See Initializing Winsock. And you should call WSACleanup() when you are done using Winsock.
1: On non-Windows platforms, there are no equivalent startup/cleanup functions that need to be called when using sockets.
Try something more like this:
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#define PORT 3000
int main()
{
WSADATA wsa;
int iResult = WSAStartup(MAKEWORD(2,0), &wsa);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return INVALID_SOCKET;
}
printf("Winsock initialized\n");
struct sockaddr_in serv_addr;
ZeroMemory(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
{
printf("Invalid address/ Address not supported \n");
WSACleanup();
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("Socket creation failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
{
printf("Connection failed: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
printf("Connection successful\n");
const char* hello = "Hello from client";
if (send(sock, hello, strlen(hello), 0) == SOCKET_ERROR)
{
printf("Send failed: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
printf("Hello message sent\n");
closesocket(sock);
WSACleanup();
return 0;
}
That said, you really should be using getaddrinfo() instead of inet_pton(), especially if you want to support both IPv4 and IPv6, eg:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#define PORT "3000"
int main()
{
WSADATA wsa;
int iResult = WSAStartup(MAKEWORD(2,0), &wsa);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return INVALID_SOCKET;
}
printf("Winsock initialized\n");
struct addrinfo hints, *addrs;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Convert IPv4 and IPv6 addresses from text to binary form
iResult = getaddrinfo("127.0.0.1", PORT, &hints, &addrs);
if (iResult != 0)
{
printf("Get Address Info failed: (%d) %s\n", iResult, gai_strerror(iResult));
WSACleanup();
return -1;
}
SOCKET sock = INVALID_SOCKET;
for(struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
{
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock != INVALID_SOCKET)
{
if (connect(sock, addr->ai_addr, addr->ai_addrlen) != SOCKET_ERROR)
break;
closesocket(sock);
sock = INVALID_SOCKET;
}
}
if (sock == INVALID_SOCKET)
{
printf("Socket creation failed/Connection failed\n");
WSACleanup();
return -1;
}
printf("Connection successful\n");
const char* hello = "Hello from client";
if (send(sock, hello, strlen(hello), 0) == SOCKET_ERROR)
{
printf("Send failed: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
printf("Hello message sent\n");
closesocket(sock);
WSACleanup();
return 0;
}
I've been doing the Winsock tutorials and following it exactly. I can't seem to get either send() or recv() to function properly. I have a basic Server and Client program set up, and the connection is being made, but the Server isn't sending a message to the Client. Using the Telnet client also doesn't receive a response from the server. I'm not really sure what's happening, and all the questions I looked at were not basic or had stuff I couldn't really understand what they were doing.
Server.cpp
#include<WinSock2.h>
#include <io.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") //winsock library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
sockaddr_in server, client;
int c;
char *message;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
else
printf("Initialised.\n");
//create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
return 2;
}
else
printf("Socket created.\n");
//prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_port = htons(8888);
//bind the socket
if (bind(s, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : &d", WSAGetLastError());
return 3;
}
else
puts("Bind done");
//listen
listen(s, 3);
//accept an incoming connection
puts("Waiting for incoming connections...");
c = sizeof(sockaddr_in);
while (new_socket = accept(s, (sockaddr *)&client, &c) != INVALID_SOCKET)
{
printf("Connect successful...\n");
//reply to the client
message = "Hello Client, I have recieved your connection, but I have to go now, bye!\n";
send(new_socket, message, strlen(message), 0);
puts("Message sent.\n");
}
if (new_socket == INVALID_SOCKET)
{
printf("accept() failed with error code : %d", WSAGetLastError());
return 4;
}
//close the socket
closesocket(s);
WSACleanup();
return 0;
}
Client.cpp
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char *argv[])
{
//intialize variables
WSADATA wsa;
char ip[100] = "192.168.1.117";
SOCKET s;
sockaddr_in server;
char *message, server_reply[75];
int recv_size;
//initialize Winsock
printf("\nInitialising Winsock...\n");
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//create the socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
return 3;
}
printf("Socket created.\n");
server.sin_addr.S_un.S_addr = inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(8888);
//connect to the server
if (connect(s, (sockaddr *)&server, sizeof(server)) < 0)
{
puts("connect error");
return 4;
}
else
{
printf("Connect successful");
recv_size = recv(s, server_reply, 75, 0);
}
if (recv_size <= 0)
{
puts("recv() failed\n");
}
else
{
//add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
}
getchar();
//close the socket
closesocket(s);
WSACleanup();
return 0;
}
The client also fails to print the "recv() failed" line; it's like it's stuck at the recv() call.
On the server side:
you are not checking the return value of listen() for error.
you are not resetting c on each call to accept(), and you are not calling closesocket() on each client that is accepted.
you are not checking the return value of send() for error.
Try this instead:
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") //winsock library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
sockaddr_in server, client;
int c, res, messagelen;
const char *message;
printf("\nInitializing Winsock...");
res = WSAStartup(MAKEWORD(2,2), &wsa);
if (res != 0)
{
printf("Failed. Error: %d\n", res);
return 1;
}
printf("Initialized.\n");
//create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket. Error: %d\n", WSAGetLastError());
return 2;
}
printf("Socket created.\n");
//prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_port = htons(8888);
//bind the socket
if (bind(s, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed. Error: &d", WSAGetLastError());
return 3;
}
printf("Bind done.\n");
//listen
if (listen(s, 3) == SOCKET_ERROR)
{
printf("Listen failed. Error: &d", WSAGetLastError());
return 4;
}
printf("Listening.\n");
//accept incoming connections
printf("Waiting for incoming connections...\n");
do
{
c = sizeof(sockaddr_in);
new_socket = accept(s, (sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("Failed to accept a client. Error: %d\n", WSAGetLastError());
return 5;
}
printf("Client connected...\n");
//reply to the client
message = "Hello Client, I have received your connection, but I have to go now, bye!\n";
messagelen = strlen(message);
do
{
res = send(new_socket, message, messagelen, 0);
if (res == SOCKET_ERROR)
{
printf("Failed to send message. Error: %d\n", WSAGetLastError());
break;
}
message += res;
messagelen -= res;
}
while (messagelen > 0);
if (messagelen == 0)
printf("Message sent.\n");
//close the client socket
closesocket(new_socket);
}
while (true);
//close the server socket
closesocket(s);
WSACleanup();
return 0;
}
On the client side, the only real problem I see is your recv() call has a potential buffer overflow waiting to happen, since you ask it to read 75 bytes, and that is the exact size of your buffer. It just happens that your server is only sending 74 bytes max, but if it ever sent more, you could overflow the buffer when appending the '\0' terminator to it.
So, either:
call recv() with sizeof(server_reply)-1 as the buffer size, to give yourself room for the added terminator:
recv_size = recv(s, server_reply, sizeof(server_reply)-1, 0);
use printf() instead of puts() so you don't need to null-terminate the buffer at all when printing it to the console. You can pass recv_size as a parameter to limit the amount of text being printed:
//server_reply[recv_size] = '\0';
//puts(server_reply);
printf("%.*s", recv_size, server_reply);
From the MSDN documentation on closesocket():
Note To assure that all data is sent and received on a connection, an application should call shutdown before calling closesocket (see Graceful shutdown, linger options, and socket closure for more information). Also note, an FD_CLOSE network event is not posted after closesocket is called.
Basically the data you have sent was still pending when you closed the socket.
I am writting a small server application which has ServerSocket object waiting for and create connection socket.
Each connection has a SocketListener and a SocketSender for transfering data.
Each SocketListener is a separate thread. When a connection is disconnect by client, SocketListener send a message to ServerSocket notify that it is closing, so that ServerSocket can clear the handle for that connection from a list.
However, don't know why the message is not received by SocketListener thread. I have tried to narrow down the message filter, but no luck. Could someone help me with this.
DWORD ServerSocket::m_ThreadFunc() {
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed\n");
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT_STR, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed\n");
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed\n");
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed\n");
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed\n");
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// allow listener thread to report back its state
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
//force create message queue
PeekMessage(&msg, NULL, WM_USER, WM_USER + 100, PM_NOREMOVE);
printf("Listing for clients on port %s \n", DEFAULT_PORT_STR);
while (listening) {
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket != INVALID_SOCKET) {
printf("Client connected\n");
sender = new SocketSender(ClientSocket);
listener = new SocketListener(ClientSocket, this->m_threadId);
printf("Listener created\n");
listener->setSender(sender);
listener->startThread();
printf("Listener started\n");
listenerList.push_back(listener);
senderList.push_back(sender);
printf("Listener list size: %d \n", listenerList.size());
printf("Listener pushed to list\n");
//delete socket data if listener close itself due to connection lost or disconnect.
}
else {
int error = WSAGetLastError();
printf("accept failed\n");
switch (error) {
case 10093:
listening = false;
try {
closesocket(ListenSocket);
}
catch (...) {}
return 1;
}
}
printf("Check message queue for thread message\n");
//check thread message queue
//GetMessage(&msg, NULL, 0, 0); //this blocks untill a message is get.
PeekMessage(&msg, NULL, WM_USER, WM_USER + 100, PM_REMOVE);
if (msg.message == WM_USER + 1)
{
//ProcessCustomMessage(msg);
m_deleteListener((SocketListener*)msg.wParam);
printf("Recieved message from ThreadID: %d \n", msg.wParam);
}
printf("Recieved message from ThreadID: %d \n", msg.message);
printf("Server socket complete 1 loop\n");
}
return 0;
}
DWORD SocketListener::m_ThreadFunc() {
listening = true;
rapidxml::xml_document<> doc;
printf("Start thread with ID: %d \n", this->m_threadId);
printf("Parent Thread ID: %d \n", this->_iParentID);
while (listening) {
int iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
recvbuf[iResult - 1] = 0; // null terminate the string according to the length
// The message spec indicates the XML will end in a "new line"
// character which can be either a newline or caraiage feed
// Search for either and replace with a NULL to terminate
if (recvbuf[iResult - 2] == '\n' || recvbuf[iResult - 2] == '\r')
recvbuf[iResult - 2] = 0;
try {
doc.parse<0>(&recvbuf[0]);
HandleXMLMessage(&doc);
}
catch (...) {}
}
else {
printf("Thread %d is being closed, sending signal to parent (%d)\n", this->m_threadId, this->_iParentID);
if (PostThreadMessage(this->_iParentID, WM_APP + 1, NULL, NULL) == 0)
{
printf("Client cant send Message before closing the conn ! \n");
printf("Last error %d", GetLastError());
}
else {
printf("Client sent Closing Message successfully \n");
}
closesocket(ClientSocket);
return 1;
}
}
printf("Server terminate connection\n");
printf("Thread %d is closed, sending signal to parent (%d)\n", this->m_threadId,this->_iParentID);
PostThreadMessage(this->_iParentID, WM_USER + 1, (WPARAM)this->m_threadId, NULL);
return 0;
}
Thank you very much.
accept function is a blocking call, so it looks like after accepting first connection your loop gets stuck at
ClientSocket = accept(ListenSocket, NULL, NULL);
And does not check thread message queue until the next connection is made.
You also need to check the return result of PeekMessage to know whether message was actually peeked otherwise msg variable will contain garbage.
I am current writing a tcp server class and a ClientHandle class for a Project.
Is it possible, that the server class simply call the select on a fd_set only containing the listensocket to check if a new client connects?
Inside of the Handle i would like to do similar with the socket to check if I got a new request or if it is writeable before sending data to it.
Something like this?
int TCPServer::start()
{
WSADATA wsaData;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo *result = nullptr, *ptr = nullptr, hints;
ZeroMemory(&hints, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(nullptr, DEFAULT_PORT, &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for the server to listen for client connections
//create socket to listen for clients
m_listensocket = INVALID_SOCKET;
m_listensocket = socket(result->ai_family, result->ai_socktype,
result->ai_protocol);
if (m_listensocket == INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(m_listensocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(m_listensocket);
WSACleanup();
return 1;
}
//free the result
freeaddrinfo(result);
//start listening
if (listen(m_listensocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(m_listensocket);
WSACleanup();
return 1;
}
//clear master set
FD_ZERO(&m_set);
//add the listen socket to the set
FD_SET(m_listensocket, &m_set);
return 0;
}
int TCPServer::acceptClient()
{
auto temp_set = m_set;
//setup the timeout to 100ms
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 100;
if (select(1, &temp_set, nullptr, nullptr, &tv) == -1)
{
//failed to select
perror("fail in select method!");
exit(4);
}
if (FD_ISSET(m_listensocket, &temp_set))
{
//we can accept a new
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept a client socket
struct sockaddr_storage their_addr; //stored address
int sin_size = sizeof their_addr;
ClientSocket = accept(m_listensocket,
reinterpret_cast<struct sockaddr *>(&their_addr),
&sin_size);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed: %d\n", WSAGetLastError());
closesocket(m_listensocket);
WSACleanup();
return 1;
}
auto handle = new ClientHandle(ClientSocket);
//now do whatever you want
}
}
Is it possible, that the server class simply call the select on a fd_set only containing the listensocket to check if a new client connects?
Yes, that's what it's for.
Inside of the Handle i would like to do similar with the socket to check if I got a new request or if it is writeable before sending data to it.
Yes, that's what it's for.