I am trying to get a server (SENSORSERVER) and client(CGI) to communicate using the send() function. The first loop round the SENSORSERVER sends the string "Hello world" to the CGI correctly, but on the second loop around the while loop, the CGI does not receive properly on the recv function.
SENSORSERVER Code
int main() {
pthread_mutex_init(&mutex, NULL);
int welcomeSocket, newSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
//pthread_create(&t0, NULL ,background(),(void *)"");
//pthread_detach(t0);
//int pthread_join();
pid = fork();
if(pid == -1){
printf("failed to fork");
}
if(pid == 0){
pthread_create(&t0, NULL, background(), (void*)"");
pthread_detach(t0);
} else {
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
while(1){
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket, 0) == 0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/*---- Send message to the socket of the incoming connection ----*/
int er = pthread_mutex_trylock(&mutex);
if (er == 0)
{
strcpy(buffer,"Hello World\n");
send(newSocket, buffer, sizeof(buffer), 0);
close(newSocket);
close(welcomeSocket);
pthread_mutex_unlock(&mutex);
}
}
}
return EXIT_SUCCESS;
}
And the CGI client code
char buf[1024];
char buf2[2024];
int main(void) {
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
/*---- Read the message from the server into the buffer ----*/
int er;
er = recv(clientSocket, buffer, sizeof(buffer), 0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
//close(clientSocket);
puts("<p>Hello <b>CGI</b</p>");
puts("</BODY>");
puts("</HTML>");
return EXIT_SUCCESS;
}
The SENSORSERVER will get to the accept() function, then when CGI gets to the receive it will carry on and continue and everything seems fine. However I need the CGI to be able to be called again and again while the SENSORSERVER is running and for the server to send the client the message. It only sends it once!
First loop round output -
Data received: Hello World
<p>Hello <b>CGI</b</p>
</BODY>
</HTML>
logout
Second loop round -
Data received:
<p>Hello <b>CGI</b</p>
</BODY>
</HTML>
logout
Can anyone see where the problem is?
The problem is that your server only accepts a single connection (the single accept
call), and then after sending the message it exits. So the second client run will get a connection failure (there's noone listening on the socket anymore) and print the blank message (as you ignore the error code).
If you want the server to be able to handle multiple connections, you need to have the accept
call in a loop. How exactly you want to do that depends on how you want to handle the connections. The simplest would be to send the message, close the accepted connection, and loop:
while (1) { /* infinite loop */
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
if (newSocket < 0) {
perror("accept");
break; }
/*---- Send message to the socket of the incoming connection ----*/
int er = pthread_mutex_trylock(&mutex);
if (er == 0) {
strcpy(buffer,"Hello World\n");
send(newSocket, buffer, sizeof(buffer), 0);
close(newSocket);
pthread_mutex_unlock(&mutex);
} else {
/* mutex lock failed (busy?) -- need to do something */
strcpy(buffer,"Error occurred\n");
send(newSocket, buffer, sizeof(buffer), 0);
close(newSocket);
}
}
close(welcomeSocket);
If you want to do anything more complex with the incoming connection, you might want to fork a process or thread to handle it, rather than doing in the loop directly, as a second connection cannot be accepted until after the first one has been handled, and the loop returns to the accept call.