WINSOCK error 10022 on listen when include thread - sockets

I am implementing a simple multithreaded FTP client server where I am facing a problem which is strange for me( as I am no master in C++ and threads).
The code I have written works normally until I #include <thread>.
Once I include the thread class the program fails on listen and gives a 10022 error. (I haven't done anything related to threads yet, only import).
Below is the code. The method is called from main().
#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h>
#include <winsock.h>
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdio.h>
#include <time.h>
#include <thread>
using namespace std;
void initializeSockets()
{
try{
logEvents("SERVER", "Initializing the server");
WSADATA wsadata;
if (WSAStartup(0x0202,&wsadata)!=0){
cout<<"Error in starting WSAStartup()\n";
logEvents("SERVER", "Error in starting WSAStartup()");
}else{
logEvents("SERVER", "WSAStartup was suuccessful");
}
gethostname(localhost,20);
cout<<"hostname: "<<localhost<< endl;
if((hp=gethostbyname(localhost)) == NULL) {
cout << "gethostbyname() cannot get local host info?"
<< WSAGetLastError() << endl;
logEvents("SERVER", "Cannot get local host info. Exiting....");
exit(1);
}
//Create the server socket
if((serverSocket = socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
throw "can't initialize socket";
//Fill-in Server Port and Address info.
serverSocketAddr.sin_family = AF_INET;
serverSocketAddr.sin_port = htons(port);
serverSocketAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//Bind the server port
if (bind(serverSocket,(LPSOCKADDR)&serverSocketAddr,sizeof(serverSocketAddr)) == SOCKET_ERROR)
throw "can't bind the socket";
cout << "Bind was successful" << endl;
logEvents("SERVER", "Socket bound successfully.");
if(listen(serverSocket,10) == SOCKET_ERROR)
throw "couldn't set up listen on socket";
else
cout << "Listen was successful" << endl;
logEvents("SERVER", "Socket now listening...");
//Connection request accepted.
acceptUserConnections();
}
catch(char* desc)
{
cerr<<str<<WSAGetLastError()<<endl;
logEvents("SERVER", desc);
}
logEvents("SERVER", "Closing client socket...");
closesocket(clientSocket);
logEvents("SERVER", "Closed. \n Closing server socket...");
closesocket(serverSocket);
logEvents("SERVER", "Closed. Performing cleanup...");
WSACleanup();
}
int main(void){
initializeSockets();
return 0;
}
I have read the thread Winsock Error 10022 on Listen but I don't think that this has solution to my problem.

Error 10022 is WSAEINVAL. The documentation for listen() clearly states:
WSAEINVAL
The socket has not been bound with bind.
The reason your code stops working when you add #include <thread> is because your call to bind() is being altered to no longer call WinSock's bind() function, but to instead call the STL's std::bind() function. Your using namespace std statement is masking that issue (this is one of many reasons why using namespace std is such a bad practice - teach yourself to stop using that!).
So you need to either:
get rid of using namespace std.
qualify bind() with the global namespace so it calls WinSock's function:
if (::bind(...) == SOCKET_ERROR)

Related

boost asio SO_REUSEPORT

I'm working on a multi-processes socket server with the boost library.
Each process run a io_service.
I want to this processes all accept on the same port.
I know SO_REUSEPORT (after linux kernel 3.9) will help.
like this python script
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('0.0.0.0', 9091))
s.listen(1)
while True:
conn, addr = s.accept()
print "new connection"
while True:
data = conn.recv(100)
print "got data", data
if not data or data == 'exit':
break
conn.close()
But I don't know how to use this option in boost asio io_service ?
For people reading this in 2019: Asio now includes a workaround in boost/asio/detail/impl/socket_ops.ipp:
#if defined(__MACH__) && defined(__APPLE__) \
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
// To implement portable behaviour for SO_REUSEADDR with UDP sockets we
// need to also set SO_REUSEPORT on BSD-based platforms.
if ((state & datagram_oriented)
&& level == SOL_SOCKET && optname == SO_REUSEADDR)
{
call_setsockopt(&msghdr::msg_namelen, s,
SOL_SOCKET, SO_REUSEPORT, optval, optlen);
}
#endif
So, socket_->set_option(udp::socket::reuse_address(true)); will set the SO_REUSEPORT option automatically if needed.
Following on from how boost/asio/socket_base.hpp defines reuse_address, I did it like this:
typedef boost::asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT> reuse_port;
socket_.set_option(reuse_port(true));
Answer by my own.
#include <iostream>
#include <string>
#include <array>
#include <boost/asio.hpp>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
int main()
{
boost::asio::io_service io;
tcp::acceptor acceptor(io);
acceptor.open(tcp::v4());
int one = 1;
setsockopt(acceptor.native_handle(), SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one));
acceptor.bind(tcp::endpoint(tcp::v4(), 9091));
acceptor.listen();
std::cout << "start" << std::endl;
for(;;)
{
tcp::socket socket(io);
acceptor.accept(socket);
std::cout << "new connections" << std::endl;
for(;;)
{
std::array<char, 4> buf;
boost::system::error_code error;
boost::asio::read(socket, boost::asio::buffer(buf), error);
if(error)
{
std::cout << "read error: " << error << std::endl;
break;
}
std::cout << "read: " << std::string(buf.data()) << std::endl;
}
}
}
The HTTP server example shows one way: http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/example/cpp11/http/server/server.cpp
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve({address, port});
acceptor_.open(endpoint.protocol());
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor_.bind(endpoint);
acceptor_.listen();
IIRC there's also an acceptor constructor that takes a boolean argument to set the reuse flag.

socket 'listen' error in C

i'm trying to create server with TCP IP protocol
But it doesn't accept connection, or may be because of listen
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd,newsockfd,num_port,serveur_T;
socklen_t client_T;
char buffer[200];
struct sockaddr_in adr_serveur, adr_client;
int n;
if (argc < 2)
{
fprintf(stderr, "nombre d'arguments est insuffisant\n");
exit(1);
}
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
error("erreur de creation de socket");
}
serveur_T=sizeof(adr_serveur);
bzero((char*)&adr_serveur, serveur_T);
num_port=atoi(argv[1]);
adr_serveur.sin_family=AF_INET;
adr_serveur.sin_addr.s_addr=INADDR_ANY;
adr_serveur.sin_port=htons(num_port);
serveur_T=sizeof(adr_serveur);
if (bind ( sockfd,(struct sockaddr *) &adr_serveur,serveur_T)<0)
{
error(" Erreur de binding");
}
listen (sockfd,5);
client_T= sizeof(adr_client);
newsockfd= accept(sockfd,(struct sockaddr *) &adr_client,&client_T);
if ( newsockfd<0)
{
error("Erreur socket accept");
}
bzero(buffer, 200);
return 0;}
When I execute server I got this error
Erreur socket accept: Operation not supported
Second question: Can I use an IRC client and connect it to my server ? In my school we have Linux servers so I'm wondering if I can use them as a hostname ?
Thanks
i'm trying to create server with TCP IP protocol
You have created a SOCK_DGRAM (UDP) socket, not a SOCK_STREAM (TCP) socket. You cannot call listen() or accept() on a UDP socket, only on a TCP socket. listen() is reporting an EOPNOTSUPP error:
listen(2)
EOPNOTSUPP
The socket is not of a type that supports the listen() operation.
You are ignoring that error, and then accept() is reporting the same error:
accept(2)
EOPNOTSUPP
The referenced socket is not of type SOCK_STREAM.
There are no connections in UDP, so there is nothing to accept. Once you have bound a UDP socket to a port, you can start calling recvfrom() and sendto() on it.
In order to connect an IRC client to this server code, you need to change the socket type to SOCK_STREAM. IRC runs on TCP, not on UDP.

d aGetting error while connecting to Postgres via dev c++

I am trying to get connected to Postgres database via Dev-c++ (Windows application and not console) for executing queries, but I am continuously getting errors.
I went through the following link:
http://www.tutorialspoint.com/postgresql/postgresql_c_cpp.htm
and added the below code to that of mine:
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[])
{
try{
connection C("dbname=testdb user=postgres password=cohondob \
hostaddr=127.0.0.1 port=5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
C.disconnect ();
}catch (const std::exception &e){
cerr << e.what() << std::endl;
return 1;
}
}
But got error stating:
'No such file or directory
#include
Compilation terminated'
Please, Can anyone help me get through this?
is there any other possible way to get connected?

How to find Address already in use?

This is my code which can run CentOS and Windows just fixing some headers.
#define _WIN32_WINNT 0x0501
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
/*
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
*/
int main()
{
int sock;
int ret = 0;
int port= 12345;
struct sockaddr_in addr;
char buf[1024];
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock<0){
printf("socket() ret = %d : %s\n",ret,strerror(errno));
return ret;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if(ret<0){
printf("bind() ret = %d errno =%d : %s\n",ret,errno,strerror(errno));
return ret;
}
printf("############# Binding port %d type Enter to stop \t",port);
fgets(buf,sizeof(buf),stdin);
return 0;
}
When I tried to bind same port by this program with runing tow process, there must be the messages that Address already in use like below.
[The first proc#centOS ]
$ ./udp
############# Binding port 12345 type Enter to stop
[The second proc#centOS]
$ ./udp
bind() ret = -1 errno =98 : Address already in use
$
However when I do same thing with same code on windows, message is different.
[The first proc#windows]
C:\ >udp
############# Binding port 12345 type Enter to stop
[The second proc#windows]
C:\ >udp
bind() ret = -1 errno =34 : Result too large
C:\ >
How can I get Address already in use on Windows?
I don't think you should use errno on windows for sockets code. You could try to use WSAGetLastError which returns WSAEADDRINUSE.
The MSDN page for errno suggests EADDRINUSE is not supported for errno.
I think you should devise a scheme where you have a my_errno function that depending on the platform uses errno or WSAGetLastError.
printf("socket() ret = %d : %s\n",ret,strerror(errno));
There may be a subtle issue with this call. The order of argument evaluation is unspecified and strerror itself can change errno, which means it has side-effects. You should print errno separately, before doing anything else.
Like cnicular said, you have to use WSAGetLastError() on Windows, not errno. To get a text message for a socket error code, you can use FormatMessage().
To answer your question, if you want to find out who is using the port, you can use the command-line netstat tool, or programmably using GetTcpTable2().

Why is Windows 7 firewall preventing PASV FTP connections?

I was trying to get CFtpServer's first example program running on a Windows 7 Pro, x64 system. After much beating around the bush and not believing what I was seeing, I got the problem down to the following simple program:
#include <iostream>
using namespace std;
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#define die(code) { cerr << "die at " << __FILE__ << " " << __LINE__ << " "; exit(code); }
int main(int argc, char **argv)
{
short port = 21;
if (argc == 2) {
port = atoi(argv[1]);
}
WSADATA WSAData;
if ( WSAStartup( MAKEWORD(2, 2), &WSAData) != 0)
die(1);
SOCKET ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//!!! proto 0 in ftpdmin!
if (ls == INVALID_SOCKET) die(1);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons( port );
if (bind( ls, (struct sockaddr *) &sin, sizeof( struct sockaddr_in ) )
== SOCKET_ERROR) die(2);
if (listen( ls, 1 ) == SOCKET_ERROR ) //!!! backlog 1 in ftpdmin!
die(3);
// wait for connect, transmit till error
SOCKET ts;
for( ;; ) {
ts = accept( ls, NULL, NULL );
if (ts == INVALID_SOCKET) die(5);
// now write some things to that socket.
int i=0;
for(;;) {
char buf[256];
sprintf(buf, "%d Testing...\r\n",i+224);
if (send(ts, buf, strlen(buf), 0) < 0) {
DWORD err = WSAGetLastError();
cerr << "send failed with " << err << endl;
break;
}
Sleep(1000);
i = (i+1)%10;
}
Sleep(1000);
closesocket(ts);
}
}
This program opens the specified socket, listens on it for connections. When it gets a connection, it proceeds to write strings that bear a passing resemblance to the string an FTP server might use to respond to the PASV command. It will keep transmitting strings, once a second, until something goes wrong.
On my system, connecting to this 'server' using the nc.exe command, I see a few strings, then the socket will close (the error printed by the 'server' is 10053).
If I disabled the Windows firewall, I see strings as long as I care to leave the nc command running.
I've seen two different variations, and I don't know what causes the difference: Sometimes it would stop when it transmitted the string '227 ', later it started dying on '229 '. It's giving every appearance of being sensitive to the text being sent.
After 3 days of beating my head on this one, I have an answer: Window KB2754804. It's a bug, known to MS since somewhere in 2011. There is a Hotfix in the referenced Knowledge base article, but it doesn't seem to work for my tests, so I had to take the alternative route of disabling the Stateful FTP firewall.
I finally got to the KB article, from this SO entry.