Connecting to a UDP Tracker in C++ - c++

I'm trying to connect to a UDP tracker server using the code below, but I'm not getting any responses from the tracker...
I gleaned what I could from this link:
http://xbtt.sourceforge.net/udp_tracker_protocol.html
and I thought I got it...but apparently not. The code executes fine and then hangs at the call to RecvFrom. So I'm guessing I'm either not sending the correct data, or I'm sending it to the wrong place.....
struct ConnectionIdRequest_t {
uint64_t connectionId;
uint32_t action;
int32_t transactionId;
} typedef ConnectionIdRequest;
const bool UdpTorrentTrackerComm::initiateConnection(const int amountUploaded,
const int amountDownloaded,
const int amountLeft) {
struct sockaddr_in serverAddress, clientAddress;
struct hostent * host;
struct in_addr address;
//Setup dummy client address
clientAddress.sin_family = AF_INET;
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
clientAddress.sin_port = htons(0);
//Setup server address
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(portNumber);
//SETUP in_addr server address
//If we have an IP
if (trackerAddress) {
if (isIp4Address(*trackerAddress)) {
//retrieve hostname from ip address
if (inet_aton(trackerAddress->c_str(), &address)) {
host = gethostbyaddr((const char *) &address, sizeof(address), AF_INET);
trackerHostname = new std::string(host->h_name);
}
else {
return false;
}
}
else {
return false;
}
}
else {
//retrieve ip address from hostname
host = gethostbyname(trackerHostname->c_str());
address.s_addr = ((struct in_addr *) host->h_addr_list)->s_addr;
trackerAddress = new std::string(inet_ntoa(address));
}
std::cout << *trackerAddress << std::endl;
//Convert trackerAddress to network format
if(!inet_aton(trackerAddress->c_str(), &serverAddress.sin_addr)) {
return false;
}
int sockFd = -1;
//Add IPv6 in the future
if ((sockFd = Socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
return false;
}
//Bind my address to the socket
if (Bind(sockFd, (struct sockaddr *) &clientAddress, sizeof(clientAddress)) == - 1) {
return false;
}
std::cout << "SendTo\n";
ConnectionIdRequest * idRequest = createConnectionIdRequest();
if (SendTo(sockFd, idRequest, sizeof(*idRequest), 0,
(struct sockaddr *) &serverAddress, sizeof(serverAddress)) == -1) {
return false;
}
timeRequestSent = clock();
std::cout << "Sent: " << idRequest->connectionId << "|||" << idRequest->action << "|||" << idRequest->transactionId << std::endl;
std::cout << "RecvFrom\n";
char buffer[3000];
socklen_t serverAddressLength = sizeof(serverAddress);
while(true) {
if (RecvFrom(sockFd, buffer, 3000, 0,
(struct sockaddr *) &serverAddress, &serverAddressLength) == - 1) {
break;
std::cout << "breaking...\n";
}
}
std::cout << "The buffer is: " << buffer << std::endl;
Close(sockFd);
return true;
}
ConnectionIdRequest * UdpTorrentTrackerComm::createConnectionIdRequest() {
ConnectionIdRequest * idRequest = new ConnectionIdRequest;
generatePeerId();
idRequest->connectionId = htonll(0x41727101980);
idRequest->action = htonl(CONNECT);
idRequest->transactionId = htonl(*peerId);
return idRequest;
}
EDIT: Alright I made the one change that Arvid suggested, but that didn't help any. I'm going through and making sure I'm converting all the bytes being sent are in network byte order...Maybe I'm missing something......

it looks like you're conflating transaction ID and peer ID. They are different. The transaction ID is the cookie you send in order to match returning packets to the correct request.
It also looks like you're not initializing the connectionID. You have to set it to the magic 64 bit number in the initial connect message. 0x41727101980
You can find an alternative protocol description here.

I ended up getting it to work. The problem was mostly that I was not converting all of the values I needed to be converting to big endian (network ordering), along with using outdated functions, (gethostbyname etc).
If you'd like more details just comment.
This is the code that works for me to establish a link with the tracker server:
NOTE: serverAddress and clientAddress are class fields of type: struct sockaddr_in
const bool UdpTorrentTrackerComm::initiateConnection() {
//Setup dummy client address
clientAddress.sin_family = AF_INET;
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
clientAddress.sin_port = htons(51413);
//Setup server address
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(portNumber);
//SETUP in_addr server address
//If we have an IP
if (trackerAddress) {
if (isIp4Address(*trackerAddress)) {
//Convert human readable trackerAddress to network byte order ip address and place in serverAddress.sin_addr
if (inet_pton(AF_INET, trackerAddress->c_str(), &(serverAddress.sin_addr))) {
//retrieve hostname and service type from ip address
char hostBuffer[100], serviceBuffer[100];
getnameinfo((struct sockaddr *) &serverAddress, sizeof(serverAddress),
hostBuffer, sizeof(hostBuffer),
serviceBuffer, sizeof(serviceBuffer),
NI_NAMEREQD | NI_DGRAM);
trackerHostname = new std::string(hostBuffer);
}
else {
return false;
}
}
else {
return false;
}
}
else {
//Setup structs to be used in getaddrinfo
struct addrinfo hints;
struct addrinfo * result, * resultPointer;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
//Convert port number to string to pass to getaddrinfo
std::stringstream ss;
ss << portNumber;
std::string portNumberString = ss.str();
//retrieve ip address from hostname--------
if (GetAddrInfo(trackerHostname->c_str(), portNumberString.c_str(), &hints, &result) != 0) {
return false;
}
//Iterate over results for IP address V4 (ADD V6 later!)
char ipBuffer[INET_ADDRSTRLEN];
for (resultPointer = result; resultPointer != NULL; resultPointer = resultPointer->ai_next) {
//If we have an IPv4 address
if (resultPointer->ai_family == AF_INET) {
//convert to presentation format and store in ipBuffer
inet_ntop(AF_INET, &((struct sockaddr_in *) resultPointer->ai_addr)->sin_addr, ipBuffer, INET_ADDRSTRLEN);
}
}
//Free result
freeaddrinfo(result);
//Convert ipBuffer to std::string and store in trackerAddress field
trackerAddress = new std::string(ipBuffer);
//Convert trackerAddress to network format
if(!inet_pton(AF_INET, trackerAddress->c_str(), &serverAddress.sin_addr)) {
return false;
}
}
int sockFd = -1;
//Add IPv6 in the future
if ((sockFd = Socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
return false;
}
//Bind my address to the socket
if (Bind(sockFd, (struct sockaddr *) &clientAddress, sizeof(clientAddress)) == - 1) {
return false;
}
//Send a request to the tracker
ConnectionIdRequest * idRequest = createConnectionIdRequest();
if (SendTo(sockFd, idRequest, sizeof(*idRequest), 0,
(struct sockaddr *) &serverAddress, sizeof(serverAddress)) == -1) {
return false;
}
timeRequestSent = clock();
//Re-send until timeout.....
ConnectionIdResponse idResponse;
socklen_t serverAddressLength = sizeof(serverAddress);
while((timeRequestSent - clock()) / 1000 < SECONDS_UNTIL_TIMEOUT) {
//Response received!
if (RecvFrom(sockFd, &idResponse, sizeof(idResponse), 0,
(struct sockaddr *) &serverAddress, &serverAddressLength) > 0) {
break;
}
}
//Set class fields that will persist
activeSocket = sockFd;
connectionId = ntohll(idResponse.connectionId);
delete idRequest;
return true;
}
Where the two structs, ConnectionIdResponse and ConnectionIdRequest are defined as:
/* Struct used to send a request for a connectionId to the tracker server.*/
struct ConnectionIdRequest_t {
uint64_t connectionId;
uint32_t action;
uint32_t transactionId;
} typedef ConnectionIdRequest;
/* Struct used in receipt of a request for a connectionId from the tracker server. */
struct ConnectionIdResponse_t {
uint32_t action;
uint32_t transactionId;
uint64_t connectionId;
} typedef ConnectionIdResponse;

Related

Why socket fails in bind after having a listenfd with same port?

Simple code first:
#include "NetFunc.h"
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
using namespace std;
void test()
{
// SOCKET listenfd = OpenListenFD("127.0.0.1", "19287");
SOCKET connfd = OpenClientFD("127.0.0.1", "12389", "127.0.0.1", "19287");
send(connfd, "test", 5, 0);
close(connfd);
using namespace std::chrono_literals;
this_thread::sleep_for(100ms);
connfd = OpenClientFD("127.0.0.1", "12389", "127.0.0.1", "19287");
send(connfd, "test2", 6, 0);
close(connfd);
// close(listenfd);
cout << "over" << endl;
return;
}
int main()
{
SOCKET listenfd = OpenListenFD("127.0.0.1", "12389");
sockaddr_storage clientaddr;
socklen_t clientlen = sizeof clientaddr;
// SOCKET connfd = 0;
const int maxNameLen = 0x800;
char* buffer = new char[0x800 + 1];
char* hostname = new char[maxNameLen + 1], * port = new char[maxNameLen + 1];
std::thread newThread{&test};
newThread.detach();
SOCKET connfd;
while (true)
{
if ((connfd = accept(listenfd, (sockaddr*)&clientaddr, &clientlen)) < 0)
{
std::cerr << "Not accept correctly at InteractWithClients" << std::endl;
}
else{
getnameinfo((sockaddr*)&clientaddr, clientlen, hostname, maxNameLen, port, maxNameLen, NI_NUMERICHOST);
std::string completeAddr = string(hostname) + ":" + string(port);
std::cout << "Addr : " << completeAddr << std::endl;
recv(connfd, buffer, 0x800, 0);
std::cout << buffer << std::endl;
}
close(connfd);
}
delete[] buffer; delete[] hostname; delete[]port;
return 0;
}
Here, the NetFunc.h has necessary headers and #define SOCKET int. It corresponds with NetFunc.cpp, which has two functions for server&client as below:
(Note that I'm trying to generate a client with a specific port, for I just need two address-port to connect rather than to distinguish a server from a client. Besides, I already use SO_REUSEADDR.)
#include "NetFunc.h"
#include <iostream>
#include <string.h>
SOCKET OpenListenFD(const char* addr, const char* port)
{
struct addrinfo hints, * listp, * p;
SOCKET listenfd;
int optval = 1;
/* Get a list of potential server addresses */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* Accept connections */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* ... on any IP address */
hints.ai_flags |= AI_NUMERICSERV; /* ... using port number */
hints.ai_family = AF_INET;
getaddrinfo(addr, port, &hints, &listp);
/* Walk the list for one that we can bind to */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
continue; /* Socket failed, try the next */
/* Eliminates "Address already in use" error from bind */
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, //line:netp:csapp:setsockopt
(setsockopt_ptr)&optval, sizeof(int));
/* Bind the descriptor to the address */
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0)
{
break; /* Success */
}
closesocket(listenfd); /* Bind failed, try the next */
}
/* Clean up */
freeaddrinfo(listp);
if (!p) /* No address worked */
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0) {
closesocket(listenfd);
return -1;
}
return listenfd;
}
SOCKET OpenClientFD(const char* serverAddr, const char* port, const char* localAddr, const char* localPort)
{
struct sockaddr_in my_addr, my_addr1;
SOCKET client = socket(AF_INET, SOCK_STREAM, 0);
if (client < 0)
std::cerr<<"Error in client creating\n";
else
std::cout << "Client Created\n";
int optval = 1;
setsockopt(client, SOL_SOCKET, SO_REUSEADDR, //line:netp:csapp:setsockopt
(setsockopt_ptr)&optval, sizeof(int));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY;
my_addr.sin_port = htons(atoi(port));
// This ip address will change according to the machine
inet_pton(AF_INET, serverAddr, &my_addr.sin_addr.s_addr);
// Explicitly assigning port number 12010 by
// binding client with that port
my_addr1.sin_family = AF_INET;
my_addr1.sin_addr.s_addr = INADDR_ANY;
my_addr1.sin_port = htons(atoi(localPort));
// This ip address will change according to the machine
inet_pton(AF_INET, localAddr, &my_addr1.sin_addr.s_addr);
if (bind(client, (struct sockaddr*)&my_addr1, sizeof(struct sockaddr_in)) == 0)
std::cout << "Binded Correctly\n";
else
{
std::cerr << "Unable to bind\n";
return -1;
}
socklen_t addr_size = sizeof my_addr;
int con = 0;
do { con = connect(client, (struct sockaddr*)&my_addr, sizeof my_addr); } while (con != 0);
if (con == 0)
std::cout << "Client Connected\n";
else
std::cerr << "Error in Connection\n";
return client;
}
My OS is Ubuntu20.04 and such code will work with normal output. However, when I remove comments in test() for listenfd, it will output Unable to bind infinitely.
I'm really a newbie in socket and network. I have no idea why that will happen. Also, is there a way for an address-port to be both server and client at the same time? (Maybe to be exact, can an address-port both connect actively & accept others' connection passively?) Thank you!
my_addr1.sin_family = AF_INET;
my_addr1.sin_addr.s_addr = INADDR_ANY;
my_addr1.sin_port = htons(atoi(localPort));
// This ip address will change according to the machine
inet_pton(AF_INET, localAddr, &my_addr1.sin_addr.s_addr);
if (bind(client, (struct sockaddr*)&my_addr1, sizeof(struct sockaddr_in)) == 0)
std::cout << "Binded Correctly\n";
This code binds a listening socket to port 19287, localPort is 19287.
// SOCKET listenfd = OpenListenFD("127.0.0.1", "19287");
And so does the commented-out code. Un-commenting it out results in two sockets attempting to listen on the same port. Surprise, surprise: this doesn't work.
The fact that the first socket that binds this port uses SO_REUSEADDR is irrelevant, and makes no difference. With or without SO_REUSEADDR, no two sockets can listen on the same port.
SO_REUSEADDR does not allow you to have multiple sockets listening on the same port, at the same time. All that SO_REUSEADDR does is allow a listening socket to be bound on a port that's temporarily "take out of commission", in specific edge cases, until a prescribed timeout expires. It allows a port to be bound as long as nothing else is listening on it, even if it's sitting in a "timeout room".
But it still won't allow you to have two different sockets listening on the same port, at the same time.

msg.controllen is 0 only on ipv6

I implement IPv6 in a network engine. I'm on the function to recv packet with UDP. This function retrieve the destination ip also with the cmsghdr structure. I have the following code
int UDPSocket::read_from_to(string& paquet, string& from, string& to, struct timeval *time_kernel /* = NULL */) {
char buffer[65535];
iovec i;
i.iov_base = buffer; // PACKET BUFFER
i.iov_len = 65535;
// A struct for the source IP address
sockaddr_in sa;
sockaddr_in6 sa_ipv6;
if (CompatibilityIPv4::Instance()->canIPv6()) {
bzero((char *) &sa_ipv6, sizeof(sa_ipv6));
sa_ipv6.sin6_family = AF_INET6;
} else {
bzero((char *) &sa, sizeof(sa));
sa.sin_family = AF_INET;
}
// Some place to store the destination address, see man cmsg
int cmsgsize = 0;
if (CompatibilityIPv4::Instance()->canIPv6()) {
cmsgsize = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(struct timeval));
} else {
cmsgsize = CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(struct timeval));
}
char cmsg[cmsgsize];
// The actual structure for recvmsg
msghdr m;
bzero(&m,sizeof(m));
if (CompatibilityIPv4::Instance()->canIPv6()) {
m.msg_name = &sa_ipv6;
m.msg_namelen = sizeof(sa_ipv6);
} else {
m.msg_name = &sa; // SOURCE IP
m.msg_namelen = sizeof(sa);
}
m.msg_iov = &i; // PACKET BUFFER, indirect
m.msg_iovlen = 1;
m.msg_control = cmsg; // FOR DESTINATION IP
m.msg_controllen = sizeof(cmsg);
// <<<< ACTUAL SYSTEM CALL >>>>
int p=recvmsg(fd, &m, 0);
std::cout << m.msg_controllen << std::endl;
In IPv4 at the end the value of m.msg_controllen is > 0 but in IPv6 it's always 0 so I can't fetch the destination IP. The sendto function is the same for IPv4/IPv6 :
if (CompatibilityIPv4::Instance()->canIPv6()) {
sockaddr_in6 sa;
bzero((char *) &sa, sizeof(sa));
sa.sin6_family = AF_INET6;
inet_pton(AF_INET6, k[0].c_str(), &sa.sin6_addr);
sa.sin6_port = htons(port);
p = sendto(fd,paquet.c_str(),paquet.size(),0,(sockaddr*)&sa, sizeof(sa));
} else {
sockaddr_in sa;
bzero((char *) &sa, sizeof(sa));
sa.sin_family = AF_INET;
inet_aton(k[0].c_str(),&sa.sin_addr);
sa.sin_port = htons(port);
p = sendto(fd,paquet.c_str(),paquet.size(),0,(sockaddr*)&sa, sizeof(sa));
}
Do you have any ideas why my m.msg_controllen is 0 on IPV6 ?
Thanks a lot !
I have solved it. I was using IPV6_PKTINFO instead of IPV6_RECVPKTINFO in my setsockopt.

udp poll sockets and multicast in C++

1) I am trying to make a simple game server using UDP. Would my code be the correct way to check if there is any reads from a single socket?
2) I want to recieve data from one user on a request ( he wants to move left), then update where the server thinks he or she is located, then broadcast the x , y coordinates. How would I implement a multicast reply with a different socket?
void run()
{
//logging file
ofstream log;
log.open("server_log.txt", ios::out | ios::app);
struct sockaddr_in myaddr; // our address
struct sockaddr_in remaddr; // remote address
socklen_t addrlen = sizeof(remaddr);
int recvlen;
int fd; // server socket that listens
int fd_reply; // this will be used to reply to all users
char buf[BUFSIZE]; // receive buffer
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(PORT);
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
std::time_t result = std::time(nullptr);
log << "Error: cannot create socket! " << "TIMESTAMP: " << std::asctime(std::localtime(&result)) << endl;
log.close();
return 0;
}
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
std::time_t result = std::time(nullptr);
log << "Error: bind failed " << "TIMESTAMP: " << std::asctime(std::localtime(&result)) << endl;
log.close();
return 0;
}
pollfd fds;
memset(fds, 0, sizeof(fds));
fds[0].fd = fd;
fds[0].events = POLLIN;
while (1)
{
int rv = poll(ufds, 1, 3500);
if (rv == -1)
{
// error occured
}
else if (rv == 0)
{
//time out
}
else
{
//check for events on fd
if (fds.revents & POLLIN)
{
recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);
}
}
}
}
Yes it looks okay.
Keep a list of all clients, and then in a loop send to all of them. To populate this list, all clients need to contact the server the first thing they do.

Create socket when have DNS name

Bellow is peace of code that I use to connect to socket in Windows. Sometimes I don't have IP dress, but have DNS name in inetAddr. Probably I must resolve address from host name, or it is possible create socket with DNS name? What is the best way to create socket when have DNS name?
commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{
...
SOCKET s;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr(inetAddr);
server.sin_family = AF_INET;
server.sin_port = htons( port );
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
FILELOGL("Could not create socket : " << WSAGetLastError(),Level::Error );
} else
{
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
FILELOGL("connect error", Level::Error);
r= commStatus::COMM_NO_TRANSMIT ;
} else
{
...
}
}
...
}
There is only one way: Resolve the host name.
Here's a part of my code that I've modified and haven't tested, but it should work:
WSADATA wsdata;
const char * inetAddr
addrinfo hints, *res;
WSAStartup (MAKEWORD (2, 2), &wsdata);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo("someaddress.com", NULL, &hints, &res) != 0)
return false;
inetAddr = inet_ntoa(((sockaddr_in *) res -> ai_addr) -> sin_addr);
You need to resolve the DNS name. Use getaddrinfo() for that. Just note that a DNS name can resolve to multiple IPs, both IPv4 and IPv6, so you have to call getaddrinfo() first in order to know how many IPs are reported, and what type of socket to create for each IP.
For example:
commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{
...
SOCKET s = INVALID_SOCKET;
struct addrinfo hint = {0};
hint.ai_flags = AI_NUMERICHOST;
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
struct addrinfo *addrs = NULL;
int ret = getaddrinfo(inetAddr, NULL, &hint, &addrs);
if (ret == EAI_NONAME)
{
hint.ai_flags = 0;
ret = getaddrinfo(inetAddr, NULL, &hint, &addrs);
}
if (ret != 0)
{
FILELOGL("Could not resolve inetAddr: " << ret, Level::Error);
}
else
{
for (struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
{
s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (s == INVALID_SOCKET)
{
FILELOGL("Could not create socket : " << WSAGetLastError(), Level::Error);
break;
}
if (connect(s, addr->ai_addr, addr->ai_addrlen) == 0)
break;
closesocket(s);
s = INVALID_SOCKET;
if (addr->ai_next == NULL)
{
FILELOGL("connect error", Level::Error);
}
}
freeaddrinfo(addrs);
if (s != INVALID_SOCKET)
{
...
}
}
...
}

C++ Sockets Does Not Work Properly

back again (sorry)
I've created a socket C++ application, but it isn't working properly.
This is my first code:
void Network::Start()
{
this->socket = Env::GetSocket();
SOCKADDR_IN sInformation;
sInformation.sin_family = AF_INET;
sInformation.sin_addr.s_addr = INADDR_ANY;
sInformation.sin_port = htons(30000);
bind(this->socket, (SOCKADDR*) (&sInformation), sizeof(sInformation));
listen(this->socket, 10);
while (true)
{
this->DO();
}
}
And the DO function:
void Network::DO()
{
SOCKET s = SOCKET_ERROR;
sockaddr_in sock_addr;
accept(s, (sockaddr*) &sock_addr, NULL);
if (INVALID_SOCKET == s)
{
return;
}
else
{
cout << "Received connection from " << inet_ntoa(sock_addr.sin_addr);
}
}
What happens, always (even if I connect) the value s is INVALID_SOCKET. I connect via a .SWF but it doesn't accept my connection. What am I doing wrong?
You are not doing adequate error handling, and you are not using accept() correctly. Try this:
void Network::Start()
{
this->socket = Env::GetSocket();
if (this->socket == INVALID_SOCKET)
{
// error
return;
}
SOCKADDR_IN sInformation = {0};
sInformation.sin_family = AF_INET;
sInformation.sin_addr.s_addr = INADDR_ANY;
sInformation.sin_port = htons(30000);
if (bind(this->socket, (SOCKADDR*) &sInformation, sizeof(sInformation)) != 0)
{
// error
return;
}
if (listen(this->socket, 10) != 0)
{
// error
return;
}
while (true)
{
this->DO();
}
}
void Network::DO()
{
SOCKADDR_IN sock_addr = {0};
socklen_t sock_addr_len = sizeof(sock_addr);
SOCKET s = accept(this->socket, (SOCKADDR*) &sock_addr, &sock_addr_len);
if (INVALID_SOCKET == s)
{
return;
}
cout << "Received connection from " << inet_ntoa(sock_addr.sin_addr);
// use s as needed. Don't forget to call close(s) or closesocket(s)
// when finished, depending on your platform...
}
accept takes the listening socket as a parameter, and returns the newly connected socket;
socklen_t length = sizeof(sockaddr_in);
s = accept(this->socket, (sockaddr*) &sock_addr, &length);
EDIT: Just tested the program, with the socket created with AF_INET, SOCK_STREAM and sInformation cleared out;
bzero((char *) &sInformation, sizeof(sInformation));
...it seems to be running well on MacOS X and linux.