I'm new to Winsock. I have an error that appears at some point mentioned in Main.cpp.
While testing with PuTTy, the client connects to the server, and then the PuTTy window immediately closes.
WSAGetLastError() says 10038 (i.e. an action on a non-socket). For some reason, it appears after the accept() call, when I try to recv() data from the socket returned by accept().
Here the source code:
(it will compile, I'm using PuTTy as the client for testing, also add WS2_32.LIB as input)
Main.cpp
#include "Server.h"
#include <iostream>
using namespace Nikson;
void main() {
Sock listen(PF_INET,SOCK_STREAM,0);
Sock client;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY;*/
SockAddr sa(AF_INET, 53000, INADDR_ANY),bb;
listen.Bind(sa);
listen.Listen();
client = listen.Accept(bb);
// **AFTER THIS CLIENT CONNECTS BUT THEN DISCONNECTS**
listen.Close();
std::cout << "Connected " << client.GetID() << WSAGetLastError();
char buf[4096];
int size;
while (true) {
size = client.Recv(buf, sizeof buf, 0);
std::cout << WSAGetLastError();
std::cin.get();
for (int i = 0; i < size; ++i)
std::cout << buf[i];
}
}
The program uses a library written by me, which wraps a Winsock SOCKET as a class:
Sock.h
#pragma once
#include <WS2tcpip.h>
#include "SockAddr.h"
namespace Nikson {
class Sock
{
public:
Sock();
Sock(int af, int type, int protocol);
Sock(const SOCKET& base);
~Sock();
int Bind(const SockAddr& sa);
int Send(const char* buf,
int len,
int flags);
int Recv(char* buf,
int len,
int flags);
int Listen();
Nikson::Sock Accept(const SockAddr& sa);
int Connect(const SockAddr& sa);
int Close();
int Shutdown(int how);
SOCKET GetID();
private:
SOCKET m_NativeID;
static inline WSAData s_WSAData;
static inline int s_SockCount=0;
};
}
Sock.cpp
#include "Sock.h"
#include <iostream>
//int Nikson::Sock::s_SockCount = 0;
Nikson::Sock::Sock()
{
if (s_SockCount == 0)
{
WORD ver = MAKEWORD(2, 2);
if ( WSAStartup(ver, &s_WSAData)!= 0) {
std::cout << "Cant Init winsock! Quiting" << std::endl;
return;
}
}
++s_SockCount;
}
Nikson::Sock::Sock(int af,int type, int protocol)
{
if (s_SockCount == 0)
{
WORD ver = MAKEWORD(2, 2);
if (WSAStartup(ver, &s_WSAData) != 0) {
std::cout << "Cant Init winsock! Quiting" << std::endl;
return;
}
}
++s_SockCount;
m_NativeID = socket(af, type, protocol);
if (m_NativeID == INVALID_SOCKET) {
std::cout << "Invalid socket";
}
}
Nikson::Sock::Sock(const SOCKET& base)
{
if (s_SockCount == 0)
{
WORD ver = MAKEWORD(2, 2);
if (WSAStartup(ver, &s_WSAData) != 0) {
std::cout << "Cant Init winsock! Quiting" << std::endl;
return;
}
}
++s_SockCount;
m_NativeID = base;
}
Nikson::Sock::~Sock()
{
closesocket(m_NativeID);
--s_SockCount;
if (s_SockCount == 0) {
WSACleanup();
}
}
int Nikson::Sock::Bind(const SockAddr& sa)
{
return bind(m_NativeID, (sockaddr*)&sa.data, sizeof(sa.data));
}
int Nikson::Sock::Send(const char* buf, int len, int flags)
{
return send(m_NativeID,buf,len,flags);
}
int Nikson::Sock::Recv(char* buf, int len, int flags)
{
return recv(m_NativeID,buf,len,flags);
}
int Nikson::Sock::Listen()
{
return listen(m_NativeID, SOMAXCONN);
}
Nikson::Sock Nikson::Sock::Accept(const SockAddr& sa)
{
int size = sizeof(sa);
return Nikson::Sock(accept(m_NativeID,(sockaddr*)&sa.data,&size));
}
int Nikson::Sock::Connect(const SockAddr& sa)
{
return connect(m_NativeID, (sockaddr*)&sa.data, sizeof(sa));
}
int Nikson::Sock::Close()
{
return closesocket(m_NativeID);
}
int Nikson::Sock::Shutdown(int how)
{
return shutdown(m_NativeID,how);
}
SOCKET Nikson::Sock::GetID()
{
return m_NativeID;
}
SockAddr.h
#pragma once
#include <WS2tcpip.h>
#include <string>
namespace Nikson {
struct SockAddr
{
SockAddr() = default;
SockAddr(int family, int port, const std::string& ip);
SockAddr(int family, int port, unsigned long ip);
sockaddr_in data;
};
}
SockAddr.cpp
#include "SockAddr.h"
Nikson::SockAddr::SockAddr(int family, int port, const std::string& ip)
{
ZeroMemory(this, sizeof * this);
data.sin_family = family;
data.sin_port = htons(port);
inet_pton(family, ip.c_str(), &(data.sin_addr));
}
Nikson::SockAddr::SockAddr(int family, int port, unsigned long ip)
{
/*ZeroMemory(this, sizeof * this);*/
data.sin_family = family;
data.sin_port = htons(port);
data.sin_addr.S_un.S_addr = ip;
}
EDIT:
This code does not use my library classes, and works fine:
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#include <thread>
#pragma comment (lib,"ws2_32.lib")
using namespace std;
void main()
{
//Initialize windsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsok = WSAStartup(ver, &wsData);
if (wsok != 0) {
cerr << "Cant Init winsock! Quiting" << endl;
return;
}
//Create a socket
SOCKETlistening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "Cant crerate a socket, Quiting" << endl;
}
//Bind the an ip adress and port to socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY;//could also use inet_pton.....
bind(listening, (sockaddr*)&hint, sizeof(hint));
// Tell winsock the socket is for listening
listen(listening, SOMAXCONN);
// wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET){}
//char host[NI_MAXHOST];
//char service[NI_MAXHOST];
//ZeroMemory(host, NI_MAXHOST);
//ZeroMemory(service, NI_MAXHOST);
//if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
// cout << host << " connected on port" << service << std::endl;
//}
//else {
// inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
// cout << host<<" connected on port "<<ntohs(client.sin_port)<<endl;
//}// close listening socket
closesocket(listening);
// while loop: accept and echo message back to client
bool running = true;
auto reciver = [&clientSocket,&running]() {
char buf[4096];
while(running) {
ZeroMemory(buf, 4096);
int byteRecived = recv(clientSocket, buf, 4096, 0);
for (int i = 0; i < byteRecived; ++i) {
cout << buf[i];
}
cout << "\n";
if (byteRecived == SOCKET_ERROR) {
cerr << "recv() error";
break;
}
if (byteRecived == 0) {
cerr << "CLient disconnected";
break;
}
}
running = false;
};
string letter;
thread listener(reciver);
while (running){
letter = "";
cin >> letter;
letter += "\n";
send(clientSocket, letter.data(), letter.size(), 0);
}
//close the socket
closesocket(clientSocket);
//Shutdown winsock
WSACleanup();
}