Send fixed array vs dynamic array over socket - c++

I am trying to send a BIGNUM (from openssl/bn.h) over socket, but its behaviour is strange.
I use BN_bn2bin() to convert BIGNUM to array of unsigned char and send it over socket using send(). But what the client receives is corrupted. Why?
Here's a minimal working sample:
server.cpp
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <cstdlib>
#include <openssl/bn.h>
using namespace std;
int main() {
// Set up
int result;
int opt_val = 1;
int port = 12345;
int listen_sock;
int peer_sock;
struct sockaddr_in address;
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = INADDR_ANY;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));
result = bind(listen_sock, (struct sockaddr*)&address, sizeof(address));
if (result != 0) {
cerr << "bind() failed." << endl;
exit(result);
}
result = listen(listen_sock, 5);
if (result != 0) {
cerr << "listen() failed." << endl;
exit(result);
}
size_t size = sizeof(address);
peer_sock = accept(listen_sock, (struct sockaddr*)&address, (socklen_t *)&size);
if (peer_sock < 0) {
cerr << "accept() failed." << endl;
exit(result);
}
////////////////////////////////
// Prepare BIGNUM
BIGNUM* bn = BN_new();
BN_rand(bn, 1024, 0, 0);
size = BN_num_bytes((const BIGNUM*)bn);
// Send using fixed array
unsigned char fixed[size];
BN_bn2bin((const BIGNUM*)bn, fixed);
// Send using dynamic array
unsigned char *dynamic;
dynamic = new unsigned char[size];
BN_bn2bin((const BIGNUM*)bn, dynamic);
// First let's compare
if ( memcmp(fixed, dynamic, size) != 0) {
cout << "Fixed and dynamic do not equal" << endl;
exit(-1);
}
// Then let's send two arrays
send(peer_sock, &size, sizeof(size), MSG_MORE);
send(peer_sock, fixed, size, MSG_MORE);
send(peer_sock, dynamic, size, MSG_MORE);
}
client.cpp
#include <netinet/in.h>
#include <iostream>
#include <netdb.h>
#include <cstdlib>
#include <arpa/inet.h>
#include <openssl/bn.h>
#include <cstring>
using namespace std;
int main() {
struct addrinfo* res;
struct sockaddr_in address;
int peer_port = 12345;
int self_sock;
string peer_ip = "127.0.0.1";
address.sin_family = AF_INET;
address.sin_port = htons(peer_port);
int result = getaddrinfo((const char*)peer_ip.c_str(), NULL, NULL, &res);
if (result != 0) {
std::cerr << "Peer hostname invalid." << std::endl;
exit(-1);
}
freeaddrinfo(res);
inet_pton(AF_INET, (const char*)peer_ip.c_str(), &(address.sin_addr));
self_sock = socket(AF_INET, SOCK_STREAM, 0);
if (::connect(self_sock, (struct sockaddr*)&address, sizeof(address)) != 0) {
std::cerr << "connect() failed." << std::endl;
exit(-1);
}
int size;
recv(self_sock, &size, sizeof(size), 0);
// Receive fixed array
unsigned char fixed[size];
unsigned char* dynamic = new unsigned char[size];
recv(self_sock, fixed, size, 0);
recv(self_sock, dynamic, size, 0);
if (memcmp(fixed, dynamic, size) != 0) {
cerr << "client: fixed and dynamic are different!" << endl;
exit(-1);
}
BIGNUM* bn_fixed = BN_new();
BIGNUM* bn_dynamic = BN_new();
BN_bin2bn((const unsigned char*)fixed, size, bn_fixed);
BN_bin2bn((const unsigned char*)dynamic, size, bn_dynamic);
if (BN_cmp((const BIGNUM*)bn_fixed, (const BIGNUM*)bn_dynamic) != 0) {
cerr << "bn_fixed and bn_dynamic are different!" << endl;
exit(-1);
}
return 0;
}
Build both with g++ -o <server/client> <server.cpp/client.cpp> -lssl -lcrypto
I used memcmp and verified that the memeory fixed and dynamic points to are equal to one another, but the fixed and dynamic client receives are totally different from each other and the original message. I doubt that it could be because I am using localhost, but when I tried using two independent machines it still happens.

Related

Cannot create a tcp connection on linux in C++

At first, here is my source code :
#include "server.h"
#include <netinet/in.h>
#include <unistd.h>
#include <thread>
#include <iostream>
#include <arpa/inet.h>
#include <sys/socket.h>
Server::Server(int port)
{
m_Port = port;
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = INADDR_ANY;
bind(server_socket, (sockaddr *)&server_address, sizeof(server_address));
listen(server_socket, SOMAXCONN);
m_Socket = server_socket;
}
Server::~Server()
{
close(m_Socket);
}
void Server::Process_Connection(const std::string message) const
{
std::cout << message << "\n";
}
void Server::Start() const
{
constexpr size_t BUFFER_SIZE = 4096;
for (;;)
{
char buffer[BUFFER_SIZE] = "";
sockaddr_in their_add;
int connection = accept(this->m_Socket, (sockaddr *)&their_add, NULL);
read(connection, buffer, 1024);
std::cout << "Received: " << buffer << "\n";
// std::cout << "Number of bytes read: " << val_read << "\n";
std::thread temp(&Server::Process_Connection, this, buffer);
temp.join();
}
}
The problem is that in the line 57, the connection
int connection = accept(this->m_Socket, (sockaddr*)&their_add, NULL);
gets a value of -1, which is an invalid connection.
Do you have any suggestions? I'm quite new to the socket programming.
Thank you in advance for your help
Instead of this:
int connection = accept(this->m_Socket, (sockaddr*)&their_add, NULL);
This:
socklen_t size = sizeof(their_add);
int connection = accept(this->m_Socket, (sockaddr*)&their_add, &size);

Issue with C++ UDP Client Hanging Up

The project I am working on uses TCP and UDP to create a file transport protocol. The TCP connection generates a random port in which it returns to the client and the client then connects to the server on that port number using UDP. UDP is then used to transfer a text file four characters a time to the server and the server will send back the characters capitalized in which will then be displayed on the client. The issue is that the client is hanging up when waiting for the server to send back the capitalized version of the characters. I will leave the code below. The part of the code that is not working is commented out towards the end of the client and server files. Any help is appreciated!
Client Code
// Libraries
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char* argv[]) {
// Variables
int port = strtol(argv[2], NULL, 10);
string file = argv[3];
int r_port;
FILE* fp;
string fileString;
string dataBuffer;
int charCounter = 0;
char c;
// *** Declare TCP socket ***
int tcpsocket = 0;
tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsocket == -1) {
cerr << "Can't create a socket";
return 1;
}
// Get host IP address
struct hostent *s;
s = gethostbyname(argv[1]);
// Setting destination info
struct sockaddr_in server;
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);
// Connect to server
int connectRes = connect(tcpsocket, (sockaddr*)&server, sizeof(server));
if (connectRes == -1) {
cerr << "Can't connect to socket";
return 1;
}
// Sending data to server
char payload[512] = "117";
int sendRes = send(tcpsocket, payload, 512, 0);
if (sendRes == -1) {
cerr << "Could not send to server";
return 1;
}
// Receive r_port from server
memset(payload, 0, sizeof(payload));
recv(tcpsocket, payload, 512, 0);
r_port = strtol(payload, NULL, 10);
close(tcpsocket);
// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
cerr << "Can't create a socket";
return 1;
}
// Get host IP address
s = gethostbyname(argv[1]);
// Setting destination info
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);
// File manipulation
fp = fopen(file.c_str(), "r");
while (c != EOF) {
c = fgetc(fp);
fileString += c;
charCounter++;
}
fclose(fp);
// UDP file transfer
for (int i = 4; i < 8; i++) {
dataBuffer += fileString[i];
}
socklen_t slen = sizeof(server);
memset(payload, 0, sizeof(payload));
strcpy(payload, dataBuffer.c_str());
sendRes = sendto(udpsocket, payload, 32, 0, (struct sockaddr *) &server, slen);
if (sendRes == -1) {
cerr << "Could not send to server";
return 1;
}
// Receive ack
// slen = sizeof(server);
// memset(payload, 0, sizeof(payload));
// recvfrom(udpsocket, payload, 32, 0, (sockaddr*)&server, &slen);
// cout << "Capitalized data: " << payload;
close(udpsocket);
return 0;
}
Server Code
// Libraries
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <cstdlib>
#include <time.h>
#include <ctype.h>
using namespace std;
// Variables
int r_port;
string fileData;
// Generate Random Port
int randomPort() {
srand(time(NULL));
return rand() % ((65535 - 1024) + 1) + 1024;
}
// Capitalization Function
string capitalize(char* payload) {
int i = 0;
char c;
string charArr;
while(payload[i]) {
c = payload[i];
charArr += toupper(c);
i++;
}
return charArr;
}
int main(int argc, char* argv[]) {
// Variables
int port = strtol(argv[1], NULL, 10);
// *** Declare TCP socket ***
int tcpsocket = 0;
tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsocket == -1) {
cerr << "Can't create a socket";
return -1;
}
// Receive data
struct sockaddr_in server;
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(tcpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
cerr << "Can't bind to IP/Port";
return -2;
}
if (listen(tcpsocket, SOMAXCONN) == -1) {
cerr << "Can't listen";
return -3;
}
struct sockaddr_in client;
char payload[512];
socklen_t clen = sizeof(client);
int clientSocket = accept(tcpsocket, (sockaddr*)&client, &clen);
if (clientSocket == -1) {
cerr << "Problem with client connecting";
return -4;
}
recv(clientSocket, payload, 512, 0);
// Check client data
if (strtol(payload,NULL,10) == 117) {
r_port = randomPort();
cout << "Handshake detected. Selected the random port " << r_port << "\n";
}
else {
cout << "Error occurred\n";
}
// Return random port
memset(payload, 0, sizeof(payload));
sprintf(payload,"%ld",r_port);
int sendRes = send(clientSocket, payload, 512, 0);
if (sendRes == -1) {
cerr << "Could not send to server\n";
return 1;
}
close(clientSocket);
close(tcpsocket);
// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
cerr << "Can't create a socket";
return -1;
}
// Receive data
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(udpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
cerr << "Can't bind to IP/Port";
return -2;
}
clen = sizeof(client);
memset(payload, 0, sizeof(payload));
recvfrom(udpsocket, payload, 32, 0, (sockaddr*)&client, &clen);
fileData = capitalize(payload);
cout << "Payload: " << fileData << "\n";
// Send ack
// socklen_t slen = sizeof(server);
// memset(payload, 0, sizeof(payload));
// strcpy(payload, fileData.c_str());
// sendRes = sendto(udpsocket, payload, 32, 0, (struct sockaddr *) &server, slen);
// if (sendRes == -1) {
// cerr << "Could not send to server";
// return 1;
// }
close(udpsocket);
return 0;
}
ssize_t sendto(**int sockfd**, const void *buf, size_t len, int flags,
const struct **sockaddr *dest_addr**, socklen_t addrlen);
Reference : https://linux.die.net/man/2/sendto
Your destination address should be : (sockaddr *) &client

Why does this simple server fail on very low concurrent request?

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
int f(int x) {
if (x == 0) return 1;
return x % 100;
}
void *deal(void *arg) {
int fd = * (int *) arg;
int x;
int n = read(fd, &x, sizeof x);
if (n < 0) std::cout << "error reading" << std::endl;
std::cout << "request " << x << " received" << std::endl;
int y = f(x);
write(fd, &y, sizeof y);
std::cout << "response to " << x << ": " << y << std::endl;
close(fd);
return NULL;
}
int main(int argc, char *argv[]) {
int port = atoi(argv[1]);
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
bind(socket_fd, (sockaddr *) &addr, sizeof addr);
listen(socket_fd, 20);
std::cout << "listen on " << port << std::endl;
sockaddr remote_addr;
socklen_t len;
for (; ;) {
int fd = accept(socket_fd, &remote_addr, &len);
pthread_t p;
pthread_create(&p, NULL, deal, (void *) &fd);
}
return 0;
}
This is the code of the server. It simply create a new thread for each connection and then read an integer, then reply the integer % 100.
It works well when there are no concurrent requests. However, it should also work on concurrent. But it failed on just 10 concurrent requests.
You are using the memory for fd time and time again in different threads. I.e. it is getting overwritten on each accept.
Change
pthread_create(&p, NULL, deal, (void *) &fd);
to
pthread_create(&p, NULL, deal, (void *) fd);
And
void *deal(void *arg) {
int fd = * (int *) arg;
to
void *deal(void *arg) {
int fd = (int) arg;

Sockets: Why is accept() hanging but connect() is succeeding?

I have been trying to understand why on my server the accept() call is still blocking when the client has a successful connect() call?
server.cpp
#include <errno.h>
#include <strings.h>
#include <iostream>
#include "globals.h"
using namespace std;
/* Declaring errno */
extern int errno;
/* Function for printing error */
void report_error(char *s)
{
printf("receiver: error in%s, errno = %d\n", s, errno);
exit(1);
}
int main(int argc, char *argv[])
{
int s,c;
int res;
struct sockaddr_in socket_address = {0}, client_sa = {0};
unsigned int client_sa_len = sizeof(client_sa);
/* Creating the socket and returns error if unsuccesfull */
if((s= socket(AF_INET, SOCK_DGRAM, PF_UNSPEC)) == -1)
report_error("socket");
socket_address.sin_family = AF_INET;
socket_address.sin_addr.s_addr=INADDR_ANY;
socket_address.sin_port = htons(5318 + 2000);
/* Binding the socket and returns error if unsuccesfull */
if(bind(s, (struct sockaddr *)&socket_address, sizeof(socket_address))== -1)
report_error("bind");
listen(s, 10);
cout << "listening on port\n";
while(1)
{
/*The server just hangs here*/
c = accept(s, (struct sockaddr*)&client_sa, &client_sa_len);
if (c > 0)
{
cout << "LOG: Was the accept successful" << endl;
res = fork();
if (res < 0)
{
perror("Forking of child failed");
}
}
if(res == 0)
{
//close(s);
char msg[MSGL], reply[50], args[MSGL];
char command[MSGL];
cout << "LOG: Get message?" << endl;
GetRequest(msg, c, &client_sa);
if( (msg[0] == 'c') && (msg[1] == 'd') && (msg[2] == ' '))
{
strncpy(command, "cd", sizeof(command));
int arg_i = 0;
for(int i = 3; msg[i] != '\n'; ++i)
{
args[arg_i] = msg[i];
++arg_i;
}
}
else
{
for(int i = 0; msg[i] != '\n'; ++i)
{
command[i] = msg[i];
}
}
else
{
if(c > 0)
{
//close(c);
}
}
}
return 0;
}
When I run this server it prints that it is listening, then when I initialize the client it does not say that the client has connected
client.cpp
#include <errno.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include "globals.h"
using namespace std;
/* Declaring errno */
extern int errno;
int main(int argc, char *argv[])
{
int s;
char* server_address = argv[1];
char command[MSGL];
char reply[MSGL];
int connect_success;
struct sockaddr_in sa = {0} ,cli_sa = {0};
int length = sizeof(sa);
struct hostent *hp;
cli_sa.sin_family = AF_INET;
cli_sa.sin_addr.s_addr=INADDR_ANY;
cli_sa.sin_port = htons(5318 + 2001);
/* FILL SOCKET ADDRESS*/
if((hp = gethostbyname(server_address))==NULL)
report_error("gethostbyname");
bcopy((char*)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
//memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
sa.sin_port = htons(5318 + 2000); /* define port number based on student ID*/
/* Creating the socket and returns error if unsuccessfull */
if((s=socket(AF_INET, SOCK_DGRAM, PF_UNSPEC))== -1)
report_error("socket");
/* Binding the socket and returns error if unsuccesfull */
if(bind(s, (struct sockaddr *)&cli_sa, sizeof(cli_sa))== -1)
report_error("bind");
connect_success = connect(s,(struct sockaddr*) &sa, length);
cout << connect_success << endl;
if (connect_success < 0)
{
report_error("connect");
cout << "LOG: is there an error?" << endl;
}
cout << "LOG: is the connection made?" << endl;
while(1)
{
cout << "myRPC>>";
fgets(command,MSGL,stdin);
if (DoOperation(command,reply,s,sa) == SEND_FAILURE)
{
cout << "Error: sending command\n";
}
}
return 0;
}
I'm fairly certain that your server process has undefined behavior.
accept() and connect() is for TCP sockets. You are creating UDP sockets. For UDP sockets, all that connect() does is set the default address for send(), and it always succeeds immediately. This is explained in the manual page for connect(2), which you should definitely read:
If the socket sockfd is of type SOCK_DGRAM, then addr is the address
to which datagrams are sent by default, and the only address from
which datagrams are received.
I expect accept() to fail for UDP (SOCK_DGRAM) sockets, most likely with EINVAL. If you review the logic in your server code, when accept() fails, res never gets initialized before its value is tested in the if() statement.
Undefined behavior.

socket programming: 'accept: Bad file descriptor'

I'm trying to write a game that will let multiple clients connect and play - below is the relevant code (it's very messy - cleaning up later):
Edit: I realized it's a lot of scrolling... the crash occurs towards the end of the game during:
std::cout << black_hits << " black hits & " << white_hits
<< " white hits.\n";
if (black_hits == 4) {
std::cout << "you won!\n";
std::cin.ignore().get();
close(client); //<<<< CRASH HERE
return 0;
}
Not really a crash I guess... but close enough :)
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define BACKLOG 10
#define MAXDATASIZE 100
typedef enum {RED,GREEN,BLUE,YELLOW,ORANGE} color;
int StartMasterMind(int client, sockaddr_storage addr_in);
struct msgstruct {
int length;
char* send_data;
};
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int tcp_connect(const char *serv, const char *host = NULL)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(host, serv, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
return 2;
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
//if (send(new_fd, "Hello, world!", 13, 0) == -1)
// perror("send");
//close(new_fd);
StartMasterMind(new_fd,their_addr);
// exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
void InitializeGame(const char* port)
{
tcp_connect(port);
}
std::vector<color> GetInputAsColorMap(char* input)
{
[...]//redacted for clarity
}
int StartMasterMind(int client, sockaddr_storage addr_in)
{
struct msgstruct message;
struct sockaddr_storage their_addr = addr_in;
socklen_t addr_len;
message.send_data = "Welcome to ... M A S T E R M I N D.\n";
message.length = strlen(message.send_data);
send(client, message.send_data, message.length, 0);
[...]//redacted for clarity
if (strcmp(theValue, "random") == 0 || strcmp(theValue, "Random") == 0)
{
[...]//redacted for clarity
}
else
{
[...]//redacted for clarity
}
char* buf;
for (int i = 0; i < 8; ++i) {
std::vector<color> current_try(4);
int black_hits = 0, white_hits = 0;
std::vector<int> correctColorIndex;
std::vector<int> correctColor;
bool exclude[4] = {false};
std::cout << "test\n";
message.send_data = "Please enter your guess: ";
message.length = strlen(message.send_data);
send(client, message.send_data, message.length, 0);
addr_len = sizeof their_addr;
std::cout << "addr_len: " << addr_len << std::endl;
recvfrom(client, buf, MAXDATASIZE-1, 0, (struct sockaddr *)&their_addr, &addr_len);
current_try = GetInputAsColorMap(buf);
std::cout << "the buffer: " << buf << std::endl;
std::cout << "current_try: " << current_try[0] << current_try[1] << current_try[2] << current_try[3] << std::endl;
[...]//redacted for clarity
std::cout << black_hits << " black hits & " << white_hits
<< " white hits.\n";
if (black_hits == 4) {
std::cout << "you won!\n";
std::cin.ignore().get();
close(client); //<<<< CRASH HERE
return 0;
}
}
[...]//redacted for clarity
}
int main(int argc, char** argv)
{
InitializeGame(argv[1]);
return 0;
}
Here is sample output:
server: waiting for connections...
server: got connection from 127.0.0.1
value or random:
1122
test
addr_len: 128
the buffer: 1123�
current_try: 1123
3 black hits & 0 white hits.
test
addr_len: 128
the buffer: 1223�
current_try: 1223
2 black hits & 1 white hits.
test
addr_len: 128
the buffer: 1122�
current_try: 1122
4 black hits & 0 white hits.
you won!
accept: Bad file descriptor
accept: Bad file descriptor
accept: Bad file descriptor
... // continuously, hundreds of times
I'm very new to socket programming; could someone give me a hand? This crashes with or without trying to close(client) at the end of the game.
I think when the child process is wrapping back to start of while(1) loop, it tries to accept a connection with server socket descriptor = "sockfd" which you already closed for the child:
if (!fork()) { // this is the child process
close(sockfd);
....
}
Try this link to read as how to terminate the child process after its work is complete.
That message means that you're calling accept() on an invalid file descriptor, i.e. probably one that you've closed.