This is a multi-client socket program.
When I am trying to run my program the few last recvfrom() do not return any data. But the recvfrom before that have the excess data. Can someone help me how to fix this.
Client:
while (1) {
memset(buff, 0, sizeof(buff));
recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr *)&servaddr,&len);
printf("%s\n", buff);
if (buff[0] == 'U') {
while(1) {
printf("Insert your username: ");
fgets(username,sizeof(username),stdin);
username[strlen(username) - 1] = '\0';
printf("Username chosen is %s\n", username);
// Username Check (Error Check)
if (strlen(username) < 1 || strlen(username) > 16) {
printf("Minimum of 1 and maximum of 16.\n");
continue;
}
for (i = 0; i < strlen(username); i++) {
if (isalnum(username[i]) == 0) {
printf("Username must contain only alphanumeric characters.\n");
j = 0;
break;
}
}
if (j = 0) {
continue;
} else {
break;
}
}
sendto(sockfd,username,strlen(username),0,(const struct sockaddr *)&servaddr,len);
memset(username, 0, sizeof(username));
} else {
break;
}
}
printf("Players:\n");
memset(buff, 0, sizeof(buff));
for (i = 0; i < numplayer; i++) {
printf("BUFF: %s\n", buff);
recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr *)&servaddr,&len);
printf("%s\n", buff);
memset(buff, 0, sizeof(buff));
}
Server:
for (i = 0; i < numplayer; i++) {
while (1) {
memset(mesg,0,sizeof(mesg));
if (recvfrom(connfd[i],mesg,sizeof(mesg),0,(struct sockaddr *)&cliaddr,&len) < 0) {
perror("Recvfrom");
exit(-1);
}
for (j = 0; j < numplayer; j++) {
if (strcmp(username[j], mesg) == 0) {
// Reinitialize buff
memset(buff, 0, sizeof(buff));
check = 1;
break;
}
}
if (check == 1) {
check = 0;
sprintf(buff, "Username already exist!");
if ( sendto(connfd[i],buff,strlen(buff),0,(const struct sockaddr *)&cliaddr,len) < 0 ) {
perror("Sendto");
exit(-1);
}
memset(buff, 0, sizeof(buff));
continue;
} else {
sprintf(buff, "Valid Username!");
if ( sendto(connfd[i],buff,strlen(buff),0,(const struct sockaddr *)&cliaddr,len) < 0 ) {
perror("Sendto");
exit(-1);
}
strcpy(username[i], mesg);
printf("Username of Player %d is %s.\n" ,i + 1,username[i]);
break;
}
}
}
printf("Players:");
for (i = 0; i < numplayer; i++) {
memset(buff, 0, sizeof(buff));
sprintf(buff, "> %s", username[i]);
printf("%s\n", buff);
for (j = 0; j < numplayer; j++) {
if ( sendto(connfd[j],buff,strlen(buff),0,(const struct sockaddr *)&cliaddr,len) < 0 ) {
perror("Sendto");
exit(-1);
}
}
}
There are no 'excess bytes'. recvfrom() returns a length. You are ignoring it. It could also be an EOS (0) or an error indication (-1, see 'errno'). You need to check all those possibilities.
TCP connection may segment the data you send to smaller packets.
If you are receiving data of known size, the receiver have to use a loop to get all the bytes of the payload.
You could find some library to do this job for you if you're new to network programming.
Boost's asio is one that I can think of, but its syntax may be a bit difficult.
Related
I've seen a similar post here, but I still can't figure out the answer.
I’m trying to do this receiving function in C on Windows:
void receiving(int server_fd){
struct sockaddr_in address;
int valread;
char buffer[2000] = {0};
int addrlen = sizeof(address);
fd_set current_sockets, ready_sockets;
//Initialize my current set
FD_ZERO(¤t_sockets);
FD_SET(server_fd, ¤t_sockets);
int k = 0;
while (1)
{
k++;
ready_sockets = current_sockets;
if (select(FD_SETSIZE, &ready_sockets, NULL, NULL, NULL) < 0)
{
perror("Error");
exit(EXIT_FAILURE);
}
for (int i = 0; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, &ready_sockets))
{
if (i == server_fd)
{
int client_socket;
if ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
FD_SET(client_socket, ¤t_sockets);
}
else
{
valread = recv(i, buffer, sizeof(buffer), 0);
printf("IP address recv2 is: %s\n", inet_ntoa(address.sin_addr));
printf("\n%s\n", buffer);
FD_CLR(i, ¤t_sockets);
}
}
}
if (k == (FD_SETSIZE * 2))
break;
}
}
Unfortunately, the program doesn’t enter in the if(FD_ISSET(i,&ready_socket)). FD_ISSET always returns 0.
Does anyone know why ?
Thanks
I have a server-client program written in C. My problem is that I have a while loop in which I receive and send data. it happens a lot when i need my server to do other things but it just stops at recv() function and waits for data from client. How can I overcome it? I've tried this:
int waitForAnswer =1;
if((childpid = fork()) == 0){
close(socketfd);
close(fd[0]);
while(1){
if(waitForAnswer) {
receive(newSocket, buff) == 0;
parseRecvMess(buff);
}
waitForAnswer =0;
but it doesn't work. For some reason the program finishes with an exit code 1, at accepting socket with a "No Socket" error.
Here is my program ;
nt main(){
int size = 256;
char buff[size];
char sbuff[size];
int n;
int reader;
int socketfd, ret;
struct sockaddr_in serverAddr;
int newSocket = -2;
struct sockaddr_in newAddr;
socklen_t addr_size;
pid_t childpid;
pocet_hracu = 0;
srand(time(NULL));
initializeLobby();
memset(buff, 0, size);
memset(sbuff, 0, size);
socketfd = socket(AF_INET,SOCK_STREAM,0);
if(socketfd < 0){
printf("\n error in socket creation");
return -1;
}
printf("\n Server socket is created\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(socketfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding\n");
return -1;
}
printf("[*]Bind to port %d\n", PORT);
if(listen(socketfd, 10) == 0){
printf("Listening...\n");
}else{
printf("Error in binding\n");
}
// pipe pro komunikaci
int readpipe;
int writepipe;
int fd[2];
pipe(fd);
for (;;) {
newSocket = accept(socketfd, (struct sockaddr *) &newAddr, &addr_size);
if (newSocket < 0) {
printf("No socket\n");
exit(1);
}
// struct timeval tv;
// tv.tv_sec = 1;
// tv.tv_usec = 0;
// setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
// read the message from client and copy it in buffer
receive(newSocket, buff);
parseRecvMess(buff);
printf("\n%s sent: %s", user, command);
if (strncmp(" new", command, 4) == 0) {
player newPlayer;
newPlayer.name = (char *) malloc(sizeof(char) * 10); // *login must contain up to 10 characters
strcpy(newPlayer.name, user);
newPlayer.gameScore = 0;
newPlayer.roundScore = 0;
newPlayer.socket = newSocket;
// TODO vztvorit pipe pro kounikaci
// newPlayer.readpipe
// newPlayer.writepipe
addToPlayersArray(&newPlayer); //TODO player index is not increasing
addToLobby(&newPlayer);
printf("Server : %s uspesne prihlasen.\n", newPlayer.name);
}
bzero(buff, size);
printf("To client : OK\n");
strcpy(sbuff, "OK\n" );
sendMess(newSocket, sbuff, sizeof(sbuff));
int waitForAnswer =1;
if((childpid = fork()) == 0){
close(socketfd);
close(fd[0]);
while(1){
printf("MAIN->while(1)\n");
// poslouchame zpravy
//if(waitForAnswer) {
receive(newSocket, buff) == 0;
parseRecvMess(buff);
//}
waitForAnswer =0;
if(strcmp(buff,":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
} else{
// send buff to parent
int i = findPlayerIndex();
memset(sbuff, '\0', size) ;
str str;
strcat(sbuff, "//:");
sprintf(str, "%d", i);
strcat(sbuff, str);
strcat(sbuff, ":");
strcat(sbuff, command);
strcat(sbuff, "\n");
write(fd[1], sbuff , strlen(sbuff)+1);
bzero(buff, sizeof(buff));
if (strncmp("roll", command, 4) == 0) {
//TODO
hod();
}
if (strncmp("none", command, 4) == 0) {
//TODO
}
strcpy(sbuff, "OK\n" );
write(newSocket, sbuff, strlen(sbuff));
bzero(buff, sizeof(buff));
bzero(sbuff, sizeof(sbuff));
}
}
}
close(fd[1]);
int nbytes = read(fd[0], buff, sizeof(buff));
printf("PARENT: buffer : %s\n",buff);
parseRecvMess(buff);
char *index1= (char *)malloc(sizeof(char)*10);
strcpy(index1, user);
int index = atoi(index1);
char *command1= (char *)malloc(sizeof(char)*10);
strcpy(command1, command);
//printf("PARENT - index:%d, command:%s\n", index, command );
printf("PARENT - index:%d, jmeno:%s, command:%s\n", index, players_array[index].name, command1 );
bzero(buff, sizeof(buff));
if (strncmp("room", command1, 4) == 0) {
// vlozit do mistnosti
printf("command = room\n");
command = strtok(command1," ");
command = strtok(NULL," "); // volba
printf("command(volba): + %s \n", command);
//int i = findPlayerIndex(); // find player in array based on user name
printf("player index: = %d \n", index);
//printPlayer(&players_array[i]);
volbaHry(&players_array[index], command, lobby);
//players_array[i].mist->pocet_hracu++;
printf("PARENT: array pocet hracu %d\n",players_array[index].mist->pocet_hracu);
printf("PARENT: lobby pocet hracu %d\n",lobby[0].pocet_hracu);
str str;
memset(sbuff, '\0', size);
//pokud v mistnosti jsou 2 hraci => zacina hra
if( players_array[index].mist->pocet_hracu == 2){
printf("Hra zacina ...\n");
hra(players_array[index].mist);
}
printMistnost(players_array[index].mist);
}
//players_array[index].mist = lobby[volba - 1];
// }
}
close(newSocket);
return 0;
}
and this is my receive() function:
int receive(int socket, char *buff){
int size = 256;
int reader = recv(socket, buff, size * sizeof(char), 0);
if (reader == -1) {
printf("BREAK reader == -1\n");
perror("recv()");
return(-1);
} else if (reader == 0) {
printf("BREAK reader == 0\n");
return(-2);
} else if(checkMessage(buff) == 0){
printf("ERROR: recieved message is not valid\n");
return(-3);
}
return 0;
}
if I'm not using waitForAnswer variable the program connects without any errors with the client, but at some points stops at the beginning of while waiting for another message.
You can also use ioctl() to check for data if the socket is set to non blocking
#include <sys/ioctl.h>
int status;
do{
ioctl(socketfd, FIONREAD, &status);
if( status > 0 ){
//packet waiting to be read
recv(socketfd, buff, size * sizeof(char), 0);
}
else{
// no data .. so do something else
}
} while (!must_stop);
Call recv with the nonblocking flag:
recv(socket, buff, size, MSG_DONTWAIT);
And the function will immediately return if there was no data to read.
I wrote this code for a simple client/server application:
This is a portion of the code of the server:
while(TRUE){
struct sockaddr_in clientName = {0};
int simpleChildSocket = 0;
unsigned int clientNameLength = sizeof(clientName);
simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);
if (simpleChildSocket == -1) {
fprintf(stderr, "Cannot accept connections!\n");
close(simpleSocket);
exit(EXIT_FAILURE);
}
/* write out our message to the client */
snprintf(buffer, sizeof(buffer), "OK %s", MESSAGE);
write(simpleChildSocket, buffer, strlen(buffer));
/* Start server operations */
array = NULL, j = 0, k = 0, numberSample = 0;
tmpValue = NULL;
do{
do{
memset(buffer, '\0', sizeof(buffer));
returnStatus = read(simpleChildSocket, buffer, sizeof(buffer));
if(returnStatus <= 0)
fprintf(stderr, "Status: %d\n", returnStatus);
for(i = 0; i < (int)strlen(buffer); i++){
if(isdigit(buffer[i]))
flag = 1;
else if(isspace(buffer[i]))
continue;
else{
flag = 0;
break;
}
}
if(flag == 0){
memset(buffer, '\0', sizeof(buffer));
snprintf(buffer, sizeof(buffer), BOLD RED "ER" RESET " Devi inserire solo numeri\n");
write(simpleChildSocket, buffer, strlen(buffer));
}
}while(flag != 1);
token = strtok(buffer, " ");
digit = atoi(token);
if(digit != 0){
printf("Token #%d: %d\n", k, digit);
k++;
}
else
printf("Ricevuto %d\n", digit);
numberSample += digit;
array = realloc(array, numberSample * sizeof(int));
for(i = 0; (tmpValue = strtok(NULL, " "))!= NULL; i++, j++){
array[j] = atoi(tmpValue);
}
}while(digit != 0);
for(i = 0; i < numberSample; i++)
printf("%d: %d\n", i, array[i]);
printf("\n\n<%d>\n\n", numberSample);
free(array);
close(simpleChildSocket);
}
Instead this is a portion of the code of the client:
/* get the message from the server */
memset(buffer, '\0', sizeof(buffer));
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
if(returnStatus > 0)
printf("%s", buffer);
else
fprintf(stderr, "Return Status: %d\n", returnStatus);
/* start client operations */
do{
memset(buffer, '\0', sizeof(buffer));
fgets(buffer, sizeof(buffer), stdin);
/*fflush(stdout);*/
write(simpleSocket, buffer, strlen(buffer));
memset(string, '\0', sizeof(string));
returnStatus = read(simpleSocket, string, sizeof(string));
if(returnStatus > 0)
printf("%s\n", string);
else
fprintf(stderr, "Return Status: %d\n", returnStatus);
}while(atoi(&buffer[0]) != 0);
The problem is that when I send data for the first time to the server, the latter goes into segmentation fault. The problem is caused by the client's read, which must take the error if the user attempts to send letters or symbols instead of the numbers. How can I fix the problem?
I am running a client which sends from the command line a timezone, and a test server (which we know works), returns the date and time for that timezone. However after returning the timezones, correctly, it segfaults.
Below is my client code:
int main(int argc, const char * argv[]){
char buf[kBufSize+1];
char line[128];
ssize_t n;
int i;
int more;
int x = 0;
int sockFD;
int port;
struct sockaddr_in sad;
struct hostent *ptrh;
sockFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
memset(&sad, 0, sizeof(sad)); /* Sets every byte of the address to be zero */
sad.sin_family = AF_INET;
/* Look up name */
ptrh = gethostbyname(argv[1]);
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Set port */
//sscanf(argv[2], "%d", &port);
port = atoi(argv[2]);
//printf("%d",port);
sad.sin_port = htons(port);
int clifd = connect(sockFD, (struct sockaddr *)&sad, sizeof(sad));
if(clifd < 0) {
printf("[ERROR]: Error Connecting...\n");
return 0;
}
printf("Number of args: %d\n", argc);
x = 3;
//printf("Value of x: %d\n", x);
//printf("[DEBUG]: Value of X: %d\n", x);
//printf("[DEBUG]: Line: %s\n", line);
do
{
/* Read input line */
do
{
more = 1;
n = read(sockFD, buf, kBufSize);
buf[n] = '\0'; // BUF IS READ FROM THE SERVER
if(n <= 0)
break;
for(i = 0; i < n; i++)
{
if(buf[i] == 10)
{
more = 0;
break;
}
}
printf("%s", buf);
if (buf == "BYE\r\n"){
printf("Closing\n");
exit(1);
}
} while(more);
if(n <= 0)
{
break;
}
strcpy(line, argv[x]);
strcat(line, "\r\n\0"); // LINE IS SENT TO THE SERVER
//printf("[DEBUG] Being sent: %s", line);
write(sockFD, line, strlen(line));
//printf("%d", n);
//printf("Value of x: %d\n", x);
x++;
} while (n != 0 && x <= argc);
close(sockFD);
return 0;
}
The argv array goes from 0 to argc-1 but you are using argv from 3 to argc. Look at the condition on your outer do/while loop.
I am trying to build a server and client for a chat server using sockets. I know that I am supposed to use select() to get input from multiple sockets, but I am not sure how to do it and still read from them properly. As my code sits, it reads perfectly fine from one client, but when two are open it ignores everything that the second client does, until the first is closed.
I am wondering how to properly implement select to make sure that I can take input from multiple sockets. Thanks in advance.
#include "../../include/my.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void interrupt();
void interrupt()
{
my_str("Server exiting.\n");
exit(0);
}
int str_to_num(char* str)
{
int i = 0;
int numDigits = 0;
int ret = 0;
while (str[numDigits] != '\0')
{
numDigits++;
}
while (i < numDigits)
{
int digit = str[i];
if (digit < 48 && digit > 57)
return -1;
digit -= 48;
ret += digit * my_pow(10, numDigits - i - 1);
i++;
}
return ret;
}
char* add_null_term(char* str)
{
int i = 0;
while (str[i] != '\0')
i++;
str[i] = '\0';
return str;
}
int main(int argc, char **argv)
{
int sockfd, newsockfd, portnum;
int len;
char buffer[256];
/*char *username = (char*)malloc(256*sizeof(char));*/
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
/*check args*/
if (argc < 2)
{
my_str("Usage: ./server <port_number>\n");
exit(0);
}
portnum = str_to_num(argv[1]);
if (portnum < 1024)
{
perror("Ports below 1024 are reserved for root access.\n");
exit(0);
}
if (portnum < 1 || portnum > 65535)
{
my_str("Port must be between 1 and 65535\n");
exit(0);
}
signal(SIGINT, interrupt);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero((char*)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portnum);
serv_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0)
{
perror("bind");
exit(0);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
while(1)
{
if ((newsockfd=accept(sockfd, (struct sockaddr*)&cli_addr, &clilen)) < 0)
{
perror("accept");
exit(0);
}
usleep(2000);
my_str("Server received: ");
while ((len = read(newsockfd, &buffer, 256)) > 0)
{
buffer[my_strlen(buffer)] = '\0';
if (my_strcmp(buffer, "/") == 0)
{
my_str("Error: command ");
my_str(buffer);
my_str("not found.\n");
bzero((char*)&buffer, sizeof(buffer));
}
/*if (count == 0)
{
my_strcpy(username, buffer);
my_str("setting nickname to: ");
my_str(username);
bzero((char*)&buffer, sizeof(buffer));
my_str(buffer);
count++;
my_str("\n");
}*/
/*else if (my_strncmp(buffer, "/me", 3) == 0)
{
my_str(username);
my_str(" ");
my_str(&buffer[4]);
bzero((char*)&buffer, sizeof(buffer));
my_str("\n");
}
else if (my_strncmp(buffer, "/nick", 5) == 0)
{
my_str("Changing nickname of ");
my_str(username);
my_strcpy(username, &buffer[6]);
my_str(" to ");
my_str(username);
bzero((char*)&buffer, sizeof(buffer));
my_str("\n");
}*/
/*else
{*/
/*my_str(username);
my_str(": ");*/
my_str(buffer);
bzero((char*)&buffer, sizeof(buffer));
my_str(buffer);
my_str("\n");
/*}*/
}
my_str("\nServer: Message end. Waiting for next connection.\n");
}
return 0;
}
If your question is HOW to use select() in a server...
Here is a snippet off the top of my head of one technique
to get you started... bear in mind all error checking is not
present, and it is not optimized to function in a round robin
basis...
listen(sockfd, SOMAXCONN)
fd_set my_set;
fd_set wk_set;
FD_ZERO(&my_set); /* initialize fd_set */
FD_SET(sock_fd, &my_set) /* put listener into fd_set */
max_fd = sockfd;
while( TRUE )
{
memcpy(&wk_set, &my_set, sizeof(my_set));
rc = select(max_fd + 1, &wk_set, NULL, NULL, NULL )
if ( rc == -1 )
{
if ( errno == EINTR )
continue;
printf("select failed: errno = %d\n", errno);
exit(1);
}
for(i = 0; i < max_fd; i++) /* check everything in wk_set */
{
if ( FD_ISSET(i, &wk_set)
{
if ( i == sockfd ) /* is it the listener socket?? */
{
wk_sock=accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if ( wk_sock == -1 )
{
printf("accept failed: errno=%d\n", errno);
exit(1);
}
FD_SET(wk_sock, &my_set); /* put into fd_set */
if ( wk_sock > max_sock )
max_sock = wk_sock;
}else{
/* ready to read from this socket */
recv_len = recv(i, .... )
if ( recv_len == 0 ) /* client disconnected */
{
close(i);
FD_CLR(i, &my_set);
if (i == max_fd )
{
for(x=0;x<max_fd;x++) /* find new max_fd */
{
if ( FD_ISSET(x, &my_set )
max_fd = x;
}
}
} else {
handle message from client
}
}
}
}
}