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();
}