So I'm using Unix Domain Socket (datagram) to communicate between two processes on my machine. The client sends queries to the server which is making some calculations and returns the result to the client.
My server receives queries from the client using recvfrom(), and my problem is that on the first time recvfrom() is being called, it does not set struct sockaddr *restrict address which is the address of the sender.
This happens only on the first time recvfrom() is being called, the following queries are working perfectly fine.
What am I doing wrong here?
client.c:
/* relevant code from client.c */
sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
memset(&client, 0, sizeof(client));
client.sun_family = AF_UNIX;
strcpy(client.sun_path, CLIENT_PATH);
bind(sockfd, (struct sockaddr *)&client, sizeof(struct sockaddr_un);
memset(&server, 0, sizeof(server));
server.sun_family = AF_UNIX;
strcpy(server.sun_path, SERVER_PATH);
while(1) {
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
FD_SET(STDIN, &readfds);
select(sockfd+1, &readfds, NULL, NULL, NULL);
if (FD_ISSET(STDIN, &readfds)) {
nbytes = read(STDIN, buf, sizeof buf);
buf[nbytes] = '\0';
if (sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *)&server,
sizeof(struct sockaddr_un)) < strlen(buf)) {
perror("send");
}
}
if (FD_ISSET(sockfd, &readfds)) {
if ((nbytes = recvfrom(sockfd, buf, MAXDATASIZE, 0, NULL, NULL)) < 0) {
perror("recv");
}
buf[nbytes] = '\0';
printf(">> %s", buf);
}
}
server.c:
/* relevant code from server.c */
FD_ZERO(&master);
FD_ZERO(&read_fds);
if ((client = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("client socket");
exit(3);
}
memset(&server, 0, sizeof(struct sockaddr_un));
server.sun_family = AF_UNIX;
strcpy(server.sun_path, SOCK_PATH);
unlink(server.sun_path);
if (bind(client, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
perror("uds bind");
exit(3);
}
FD_SET(client, &master);
// keep track of the biggest file descriptor
fdmax = client; //so far, it's this one
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == client) {
// data is from client console
if ((nbytes = recvfrom(i, &buf, sizeof buf, 0, (struct sockaddr *)&client_addr, &remotelen)) <= 0) {
if (nbytes == 0) {
FD_CLR(i, &master);
close(i);
} else {
perror("client: recv");
}
}
buf[nbytes-1] = '\0';
if (strcmp(buf, "command-1") == 0) {
if ((nbytes = sendto(i, cmd1_str, strlen(cmd1_str), 0, (struct sockaddr *)&client_addr, remotelen)) < 0) {
perror("sendto");
}
buf[0] = '\0';
} else {
sendto(i, unknown_str, strlen(unknown_str), 0, (struct sockaddr *)&client_addr, remotelen);
buf[0] = '\0';
}
}
}
} // END got new incoming connection
} // END looping through file descriptors
} // END for(;;)--and you thought it would never end!
Code was trimmed a to include only what's supposed to be important and relevant. Please, if anything important is missing, let me know and I'll add it.
Related
I'm trying to implement an application using select(), but without closing the socket already served and without removing the corrispondent file descriptor from the main set of monitored socket (at least not immediatly). The goal is to create something similar to a set of "persistent connections".
The problem is that after I checked the ready socket, recv() continue to receive the last message a peer sent (running the code below, "Received" is printed infinited times). My thought is that the socket is still "ready", but I can't "mark" it as "unready" or "unchecked" to check it again only if there's a new message from that peer, and close it only in determinate conditions. How can I mark that socket as unready without close it? Is there another solution to implement persistent connections with select()?
Here it is a code of a simple application that I'm trying to program to understand how to realize persistent connections.
Server:
int main () {
int ret, sd, new_sd, len, i;
char buffer[1024];
fd_set master;
fd_set read_fds;
int fdmax;
struct sockaddr_in my_addr;
FD_ZERO(&master);
FD_ZERO(&read_fds);
sd = socket(AF_INET, SOCK_STREAM, 0);
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4257);
my_addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sd, (struct sockaddr*)&my_addr, sizeof(my_addr));
if(ret<0) {
perror("Error: ");
exit(1);
}
ret = listen(sd,10);
if(ret<0) {
perror("Error: ");
exit(-1);
}
FD_SET(sd, &master);
fdmax = sd;
for(;;) {
read_fds = master;
select(fdmax+1, &read_fds, NULL, NULL, NULL);
for(i=0; i<=fdmax; i++) {
if(FD_ISSET(i, &read_fds)) {
if(i == sd) {
len = sizeof(cl_addr);
new_sd = accept(sd, (struct sockaddr*)&cl_addr, &len);
FD_SET(new_sd, &master);
if(new_sd > fdmax)
fdmax = new_sd;
}
else {
ret = recv(i, buffer, 4, 0);
printf("Error: %s\n", strerror(errno));
printf("Received.\n");
if(strcmp(buffer, "DEL")==0) { /*Connection is closed only if client request it*/
close(i);
FD_CLR(i, &master);
printf("%d closed.\n",i);
continue;
}
len=strlen(buffer);
ret = send(i, (void*)buffer, len, 0);
if(ret<0) {
printf("socket n%d :\n",i);
perror("Error \n");
}
}
}
}
}
close(sd);
return 0;
}
I would be really grateful if you would help me, it is very important to me.
Edit: Client side is correct and send only once. "printf("Error: %s\n", strerror(errno));" print always "Success". After the first correct receiving, the program print infinite times these two printf after recv and buffer is empty.
Client:
int main (int argc, char* argv[]) {
int ret, sd, i, len;
char buffer[1024];
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[1]));
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
for(;;) {
scanf("%s",buffer);
if(strcmp(buffer,"c")==0) {
sd = socket(AF_INET, SOCK_STREAM, 0);
ret = connect(sd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(ret<0) {
perror("Error ");
exit(1);
}
}
if(strcmp(buffer, "REQ\0")==0) {
ret = send(sd, buffer, sizeof(buffer), 0);
if(ret<0) {
perror("Error ");
exit(1);
}
ret = recv(sd, (void*)buffer, 7, 0);
if(ret<0) {
perror("Error ");
exit(1);
}
printf("Received: %s\n", buffer);
}
if(strcmp(buffer, "DEL\0")==0) {
ret = send(sd, buffer, sizeof(buffer), 0);
if(ret<0) {
perror("Error ");
exit(1);
}
close(sd);
return 0;
}
}
}
I've set up a very simple C socket server, there are two files.
main.c:
#include "socket_server.h"
#include "main.h"
int main (int argc, char* argv[])
{
start_socket_server(SOCKET_SERVER_PORT);
while (1)
{
update_clients();
}
return 0;
}
socket_server.c:
#include "socket_server.h"
int listen_fd, fdmax, newfd, nbytes, i, j, k;
char buf[256];
fd_set master;
fd_set read_fds;
struct timeval tv;
void start_socket_server(int port)
{
struct sockaddr_in servaddr;
FD_ZERO(&master);
FD_ZERO(&read_fds);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port);
tv.tv_sec = 0;
tv.tv_usec = 100;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
FD_SET(listen_fd, &master);
fdmax = listen_fd;
}
void update_clients()
{
read_fds = master;
select(fdmax+1, &read_fds, NULL, NULL, &tv);
for(i = 0; i<= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
if (i == listen_fd) //new connection
{
newfd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (newfd != -1)
{
fprintf(stderr, "New connection!");
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
}
} else {
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
for(j = 0; j <= fdmax; j++)
{
if(FD_ISSET(j, &master))
{
if(j != listen_fd && j != i)
{
fprintf(stderr, "%s", buf);
}
}
}
}
}
}
}
}
Then I have a simple flash file to connect to it with the following actionscript:
var socket = new XMLSocket;
socket.connect("12.34.56.78", 8080);
socket.onConnect = function(status) {
if(status) {
trace("connected");
socket.writeUTF("Hello!");
socket.flush();
} else {
trace("couldn't connect");
}
};
If I run the server, then my actionscript, I would expect the following:
Server sits and waits
Flash file starts
Server says "New connection!" and flash file says "connected"
Server says "Hello!".
Only 1-3 happen. "Hello!" is never output to my terminal. In fact as best I can tell this block:
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
for(j = 0; j <= fdmax; j++)
{
if(FD_ISSET(j, &master))
{
if(j != listen_fd && j != i)
{
fprintf(stderr, "%s", buf);
}
}
}
}
Is never executed at all (except for when I close my flash file and the server prints "Dead".
What's going on? Why can't I see the data sent from flash? I've managed to send data TO flash, but I haven't been able to receive any FROM it. Also this is being run from within flash, so there is no need to worry about policy files at this stage.
You need to set all your sockets to be non-blocking. For example,
void start_socket_server(int port)
{
struct sockaddr_in servaddr;
int val;
FD_ZERO(&master);
FD_ZERO(&read_fds);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port);
tv.tv_sec = 0;
tv.tv_usec = 100;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == ioctl(listen_fd, FIONBIO, (val = 1, &val)))
{
perror("ioctl failed!\n");
goto ERROR; /* TODO: or however else you want to deal with errors */
}
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
FD_SET(listen_fd, &master);
fdmax = listen_fd;
}
...
if (i == listen_fd) //new connection
{
newfd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (newfd != -1)
{
int val;
fprintf(stderr, "New connection!");
if (-1 == ioctl(newfd, FIONBIO, (val = 1, &val)))
{
perror("ioctl failed!\n");
goto ERROR; /* TODO: or however else you want to deal with errors */
}
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
}
} else {
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
fprintf(stdout, "Received %d bytes: '%s'\n", nbytes, buf);
}
}
You should also do this on your main listening socket too after you create it initially so that you can't get stuck in a call to accept() somehow.
Also, the way you are outputting read-in data doesn't make much sense. As initially posted, the code would only print out if it had multiple client connections established. Then, when data was read in, it would print it N - 1 times, where N was the number of current client connections.
I need help debugging some code for a multiplayer game with a single server (acting as a master) and multiple clients. I want to connect those multiple clients to the server using the select and FD_Set functions.
Once the client connects to the server, I save their file descriptor in an array and check if data is available on file to read (using select). If yes, read the data, else I want to broadcast a message to all clients. This is run repeatedly in a loop. Every second, I want to broadcast a message to all clients. At the same time, I want to receive data from client too. So I am checking the availabity of data with the help of select function.
Here is my code:
Server.c:
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include "sys/select.h"
#include <fcntl.h>
#define PORT 5000
#define BUF_SIZE 2000
#define CLADDR_LEN 100
int arr[4] = { 0 };
char clientAddr[4][CLADDR_LEN];
void main() {
struct sockaddr_in addr, cl_addr;
int sockfd, len, ret, newsockfd;
char buffer[BUF_SIZE];
fd_set fds;
int maxfd = -1;
int i = 0, j = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = PORT;
ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error binding!\n");
exit(1);
}
printf("Binding done...\n");
printf("Waiting for a connection...\n");
listen(sockfd, 4);
for (j = 0; j < 2; j++) { //infinite loop
len = sizeof(cl_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cl_addr, &len);
if (newsockfd < 0) {
printf("Error accepting connection!\n");
exit(1);
}
printf("Connection accepted...\n");
inet_ntop(AF_INET, &(cl_addr.sin_addr), clientAddr[j], CLADDR_LEN);
arr[j] = newsockfd;
printf("\n%d", newsockfd);
//FD_ZERO(&fds);
//FD_SET(newsockfd, &fds);
}
close(sockfd);
for (j = 0; j < 2; j++) {
if (arr[j] > maxfd)
maxfd = arr[j];
// FD_SET(arr[j], &fds);
// fcntl(arr[i], F_SETFL, O_NONBLOCK); //stop listening for new connections by the main process.
} //the child will continue to listen.
//the main process now handles the connected client.
while (1) {
for (i = 0; i < 2; i++) {
FD_SET(arr[i], &fds);
}
int returned = select(maxfd + 1, &fds, NULL, NULL, NULL);
if (returned) {
for (i = 0; i < 2; i++) {
if (FD_ISSET(arr[2], &fds)) {
ret = recvfrom(arr[i], (void*) &buffer, sizeof(buffer), 0,
NULL, NULL);
if (ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
printf("%s", buffer);
}
}
}
for (j = 0; j < 2; j++) {
ret = sendto(arr[j], "abc", BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, len);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
printf("Sent data to %s: %s\n", clientAddr[j], buffer);
}
}
/*while (1) {
for (j = 0; j < 2; j++) {
memset(buffer, 0, BUF_SIZE);
if (FD_ISSET(arr[j], &fds)) {
ret = recvfrom(arr[j], buffer, BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, &len);
if (ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
printf("Received data from %s: %s\n", clientAddr[j], buffer);
}
}
for (j = 0; j < 2; j++) {
ret = sendto(arr[j], "abc", BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, len);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
printf("Sent data to %s: %s\n", clientAddr[j], buffer);
}
/* close(arr[0]);
close[arr[1]);
close(arr[2]);
close(arr[3]);
}*/
}
client.c:
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include"netdb.h"
#define PORT 5555
#define BUF_SIZE 2000
int main(int argc, char**argv) {
struct sockaddr_in addr, cl_addr;
int sockfd, ret;
char buffer[BUF_SIZE];
struct hostent * server;
char * serverAddr;
if (argc < 2) {
printf("usage: client < ip address >\n");
exit(1);
}
serverAddr = argv[1];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(serverAddr);
addr.sin_port = PORT;
ret = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error connecting to the server!\n");
exit(1);
}
printf("Connected to the server...\n");
memset(buffer, 0, BUF_SIZE);
//printf("Enter your message(s): ");
//while (fgets(buffer, BUF_SIZE, stdin) != NULL) {
sleep(10);
ret = sendto(sockfd, "a", BUF_SIZE, 0, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error sending data!\n\t-%s", buffer);
}
ret = recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
if (ret < 0) {
printf("Error receiving data!\n");
} else {
printf("Received: ");
fputs(buffer, stdout);
printf("\n");
}
return 0;
}
(The client is passed an IP address.)
This does not work. While debugging the server, it waits at select and nothing is received or sent. What might the problem be?
Probably because you aren't listening on the right port. The sockaddr_in members needs to be configured in network byte order:
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
above is example how select works, in a while loop you must set timeval structure and socket sd
while (1) {
FD_ZERO(&readfds);
FD_SET(sd, &readfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = select(sd + 1, &readfds, NULL, NULL, &tv);
if (rv == 1) {
/*recvfrom*/
}
}
In security firstly FD_ZERO(&readfds)
and you not have to FDSET your clientfds every while loop. You can set one time before the while.
Id u check the client side and clients send data succesfully check the this line
for (i = 0; i < 2; i++) {
if (FD_ISSET(arr[2], &fds)) {
ret = recvfrom(arr[i], (void*) &buffer, sizeof(buffer), 0,
NULL, NULL);
In your code FD_ISSET(arr[2], &fds) you can change the like this
FD_ISSET(arr[i], &fds) because your for loop do nothing here if you can not change the arr[i]
I am working on client server code where I have two threads running at client side (bulk and retail) and I have two ports at server to receive data. I want to use select() at server side but doing some mistake due to which data is never getting received at "sd1 - which is bulk port". I will really appreciate if someone could help me out as how to go ahead with current code. Thanks!!
int main(int argc, char *argv[]) {
fd_set readfds, activefds;
// SOCKET CREATION RETAIL
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0) {
printf("error creating retail socket \n");
return -1;
}
// SOCKET CREATION BULK
sd1=socket(AF_INET, SOCK_DGRAM, 0);
if(sd1<0) {
printf("error creating retail socket \n");
return -1;
}
// BIND RETAIL PORT
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(RETAIL_PORT);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {
printf("error binding retail port number %d \n",RETAIL_PORT);
return -1;
}
// BIND BULK PORT
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(BULK_PORT);
rc1 = bind (sd1, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc1<0) {
printf("error binding bulk port number %d \n",BULK_PORT);
return -1;
}
int nfds;
if(sd>sd1){
nfds = sd;}
else{
nfds = sd1;}
FD_ZERO(&activefds);
FD_SET(sd, &activefds);
FD_SET(sd1, &activefds);
while(1){
readfds = activefds;
if (select(nfds+1, &readfds, NULL, NULL, NULL) < 0){
perror("select");
break;
}
for(i=0;i<nfds;i++){
if(FD_ISSET(i, &readfds)){
printf("sd = %d\n\n\n",sd); // sd = 3 getting printed here
if(i == sd){
n = recvfrom(sd, &requested_retail_cases, 4, 0, (struct sockaddr *) &cliAddr, &cliLen);
printf("in retail\n");
}
else if(FD_ISSET(i, &readfds)){
if(i == sd1){
n1 = recvfrom(sd1, &requested_bulk_cases, 4, 0, (struct sockaddr *) &cliAddr, &cliLen);
}
}
}
}
return 1;
}
Change
if(FD_ISSET(i, &readfds)){
if(i == sd){
...
}
else if(FD_ISSET(i, &readfds)){
if(i == sd1){
...
}
}
to
if(FD_ISSET(i, &readfds)){
if(i == sd){
...
}
else if(i == sd1){
...
}
}
As it stands in your code, the second outer if is never reached. You effectively have if (x) then y; else if (x) then z; Obviously, the second if is never reached.
I'm trying to make a server that can be connected to by multiple clients. Here's my code so far:
Client:
int main(int argc, char **argv) {
struct sockaddr_in servaddr;
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1) perror("Socket");
bzero((void *) &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6782);
servaddr.sin_addr.s_addr = inet_addr(<server_ip_address>);
if (-1 == connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)))
perror("Connect");
while(1) {
char message[6];
fgets(message, 6, stdin);
message[5] = '\0';
send(sock, message, 6, 0);
}
close(sock);
}
Server:
int main(int argc, char **argv) {
fd_set fds, readfds;
int i, clientaddrlen;
int clientsock[2], rc, numsocks = 0, maxsocks = 2;
int serversock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serversock == -1) perror("Socket");
struct sockaddr_in serveraddr, clientaddr;
bzero(&serveraddr, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(6782);
if (-1 == bind(serversock, (struct sockaddr *)&serveraddr,
sizeof(struct sockaddr_in)))
perror("Bind");
if (-1 == listen(serversock, SOMAXCONN))
perror("Listen");
FD_ZERO(&fds);
FD_SET(serversock, &fds);
while(1) {
readfds = fds;
rc = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
if (rc == -1) {
perror("Select");
break;
}
for (i = 0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &readfds)) {
if (i == serversock) {
if (numsocks < maxsocks) {
clientsock[numsocks] = accept(serversock,
(struct sockaddr *) &clientaddr,
(socklen_t *)&clientaddrlen);
if (clientsock[numsocks] == -1) perror("Accept");
FD_SET(clientsock[numsocks], &fds);
numsocks++;
} else {
printf("Ran out of socket space.\n");
}
} else {
int messageLength = 5;
char message[messageLength+1];
int in, index = 0, limit = messageLength+1;
while ((in = recv(clientsock[i], &message[index], limit, 0)) > 0) {
index += in;
limit -= in;
}
printf("%d\n", index);
printf("%s\n", message);
}
}
}
}
close(serversock);
return 0;
}
As soon as a client connects and sends its first message, the server just runs in an infinite loop, and spits out garbage from the message array. recv doesn't seem to receive anything. Can anyone see where i go wrong?
Two issues in your code:
You should do recv(i, ...) instead of recv(clientsock[i], ...)
After that you do not check if recv() failed, and therefore printf() prints out the uninitialised buffer message, hence the garbage in the output
You need to check for limit <= 0 in your read loop, before you call read.
In the while loop for the server, change the code to do recv(i) instead of recv(clientsocks[i]). I have implemented this code and it works with this change.
I replaced the else with the below and it works
} else {
/* int messageLength = 5;
char message[messageLength+1];
int in, index = 0, limit = messageLength+1;
memset ( &message[index] , 0, sizeof ( message [index] ) );
while ((in = recv(i, &message[index], limit, 0)) > 0) {
index += in;
limit -= in;
}
printf("%d\n", index);
printf("%s\n", message);
*/
bzero(buf, sizeof(buf));
if ((rval = read(i, buf, 1024)) < 0)
perror("reading stream message");
else if (rval == 0)
printf("Ending connection\n");
else
printf("-->%s\n", buf);
}
1) It is a good practice to use PF_INET(protocol family) rather than
AF_INET(address family) during the Socket creation .
2) within the while(1) loop
each time it is advisable to make your readfds empty by using FD_ZERO(&readfds).
in the recv() call you should use i rather than clientsocks[i]
you have to check return value of recv is negative(which indicating error in reading) if that is the case you do not have to print the message.
during printing the message make sure the stdout/server is ready for writing anything to it which you can do it by using writefds (3rd argument of select).