Server Client program in C using sockets and tcp - c

I have written a program for simple text chatting between server and client using socket programming. The server side runs okay since it's listening but when I run the client side program it runs but shows no output, meaning nothing shows up on server side if I type in Client side. Why am I not getting any response from Client side?
/****************** CLIENT CODE ****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int clientSocket,n;
char buffer[256];
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);
if (connect(clientSocket,(struct sockaddr *) &serverAddr,sizeof(serverAddr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(clientSocket,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(clientSocket,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(clientSocket);
/*---- Read the message from the server into the buffer ----*/
//recv(clientSocket, buffer, 1024, 0);
/*---- Print the received message ----*/
//printf("Data received: %s",buffer);
return 0;
}
/****************** SERVER CODE ****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int welcomeSocket, newSocket;
char buffer[256];
int n;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
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,5)==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 ----*/
bzero(buffer,256);
n = read(welcomeSocket,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(welcomeSocket,"I got your message",18);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(welcomeSocket,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
close(newSocket);
close(welcomeSocket);
return 0;
}

In your server code the read() should use the socket descriptor returned from the accept() not from the call to socket(). So try reading using newSocket rather than welcomeSocket.
n = read(newSocket,buffer,255);

Related

UDP socket demultiplexing at server port

TCP socket demultiplexing at the server port (which listens for multiple TCP connections) happens with a separate socket descriptor created for each established TCP connection(though the accept() call) and the socket descriptor is tightly coupled with tuple [source IP address, source port, destination IP address, destination IP address]. Over this established connection we can use the high layer application protocols like HTTP, FTP, SSH etc.,
But in case of UDP there is no session/connection established between the peers. The server waiting at the particular port receives the message from any client. The client's IP address and port number is known after receiving the message(populated in the socket address structure). From the address structure the messages can be demultiplexed and given to respective applications.
Over the server port, If I want to establish a connected session over UDP[like the tuple mentioned in case of TCP] so that communication between the server and client (between particular port on server and client) can be demultiplexed before receiving the message(without inferring the same from socket address structure) so that the higher layer protocols can work like on TCP (ofcourse higher layer protocols like DTLS taking care of the reliability)
Below is the code for UDP server(leveraging the connect() API to keep the UDP socket connected) and UDP client
// server program for udp connection
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PORT 5000
#define MAXLINE 1000
//logical thread num
static unsigned int threadnum = 0;
struct pass_info {
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
unsigned int threadnum;
};
char *message = "Hello Client";
void* connection_handle(void *info) {
int fd = 0;
char buffer[100];
int n = 0;
const int on = 1;
struct pass_info *pinfo = (struct pass_info*) info;
printf("Executing thread : %d\n", pinfo->threadnum);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Error socket!!!");
return;
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
bind(fd, (const struct sockaddr *) &pinfo->server_addr, sizeof(struct sockaddr_in));
connect(fd, (struct sockaddr *) &pinfo->client_addr, sizeof(struct sockaddr_in));
while(1)
{
n = recv(fd, buffer, sizeof(buffer), 0);
if (n < 0)
{
printf("receive failed! in thread : %d", pinfo->threadnum);
break;
}
buffer[n] = '\0';
printf("Thread num %d: Recv message - %s\n", pinfo->threadnum, buffer);
n = send(fd, message, sizeof(message), 0);
if (n < 0)
{
printf("send failed! in thread : %d", pinfo->threadnum);
break;
}
}
free(info);
return NULL;
}
int main()
{
char buffer[100];
int listenfd, len, sockfd;
const int on = 1;
struct sockaddr_in servaddr, cliaddr;
bzero(&servaddr, sizeof(servaddr));
struct pass_info *info;
pthread_t tid;
// Create a UDP Socket
listenfd = socket(AF_INET, SOCK_DGRAM, 0);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
// bind server address to socket descriptor
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
while (1)
{
//receive the datagram
len = sizeof(cliaddr);
int n = recvfrom(listenfd, buffer, sizeof(buffer),
0, (struct sockaddr*)&cliaddr,&len); //receive message from server
buffer[n] = '\0';
printf("Main thread: Recv message - %s\n", buffer);
n = sendto(listenfd, message, MAXLINE, 0, (struct sockaddr*)&cliaddr, sizeof(cliaddr));
info = (struct pass_info*) malloc (sizeof(struct pass_info));
memcpy(&info->server_addr, &servaddr, sizeof(struct sockaddr_in));
memcpy(&info->client_addr, &cliaddr, sizeof(struct sockaddr_in));
threadnum++;
info->threadnum = threadnum;
if (pthread_create(&tid, NULL, connection_handle, info) != 0) {
perror("pthread_create");
exit(-1);
}
}
}
// udp client program
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#define PORT 5000
#define MAXLINE 1000
int main()
{
char buffer[100];
char *message = "Hello Server";
int sockfd, n;
struct sockaddr_in servaddr, cliaddr;
int len = 0;
// clear servaddr
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
// create datagram socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
while(1)
{
sleep(3);
sendto(sockfd, message, MAXLINE, 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
// waiting for response
recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &len);
puts(buffer);
}
}
Queries:
Whether this would be the right way to do de-multiplexing at the UDP socket level
The server listens for any UDP packets from the client. once it receives a message, new socket descriptor is created and the connect() API is called so that the client's IP address, port is registered with this newly created socket descriptor and from here on newly created socket descriptor will used to send and receive messages to the particular client's IP address and port. Whether it is a fool proof method
Are there any other well known methods to use the higher layer protocols(protocols supporting reliability like DTLS) over UDP

Client connects to server randomly

I am trying to write a simple client/server program where the server first connects to the client, and sends the client a message. The client then echoes back the message to the server in uppercase.
The thing is, the connection is random; sometimes the client connects and sometimes it doesn't.
EDIT: when it doesn't connect, I get an "Address already in use" error. Is there some way to free the address on the server side?
SERVER.C
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
int main(){
int welcomeSocket, newSocket, portNum, clientLen, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
int counter = 0;
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
portNum = 7891;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portNum);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
while(1){
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/* counter ++ ;*/
/* printf("client connected: %d\n",counter);*/
/*fork a child process to handle the new connection*/
if(!fork()){
/*---- Send message to the socket of the incoming connection ----*/
strcpy(buffer,"Hello World\n");
send(newSocket,buffer,13,0);
recv(newSocket,buffer,13,0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
close(newSocket);
exit(0);
}
/*if parent, close the socket and go back to listening new requests*/
else{
close(newSocket);
}
}
return 0;
}
CLIENT.C
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>
int main(){
int clientSocket, portNum, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
portNum = 7891;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portNum);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
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 ----*/
nBytes = recv(clientSocket, buffer, 1024, 0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
for (int i=0;i<nBytes-1;i++){
buffer[i] = toupper(buffer[i]);
}
send(clientSocket,buffer,nBytes,0);
return 0;
}
The "address already in use" error occurrs on a call to bind when a socket is already bound to that port. In the case of a listening TCP socket, that can happen when the program is restarted due to old connected sockets not being completely closed yet.
When binding a listening socket, you should set the SO_REUSEADDR socket option. This will allow you to bind a TCP listening socket in these situations.
int option = 1;
if (setsockopt(welcomeSocket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) == -1) {
perror("setsockopt for SO_REUSEADDR failed");
exit(1);
}
This function should be called after socket but before bind.

Socket Programming (Client - Server UDP)

I would like to build a client - server model where, for any number of clients connected to the server, the server should send a broadcast Message. Below is the code which I implemented, it does not throw any error, but I could not see any communication happening between the server and the client. Please let me know, where is the problem in the code.
I would like to see the message passed from the server on the clients system.
/************* UDP SERVER CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int udpSocket, nBytes, buflen;
char buffer[1024];
char string[1024];
int portNum;
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/*Create UDP socket*/
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum=atoi(argv[1]);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5000);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*Bind socket with address struct*/
int bStatus=bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (bStatus < 0) {
printf("error binding on server's port number\n");
exit(1);
}
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum); // this is where client is bound
clientAddr.sin_addr.s_addr = inet_addr("192.168.1.114");
while(1){
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
int bytesSent = sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&clientAddr, sizeof(clientAddr));
if (bytesSent < 0) {
printf("Error sending/ communicating with client\n");
exit(1);
}
printf("%s\n",buffer);
/*
// ****************************************************
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage, &addr_size);
printf("Received from server: %s\n",buffer);
*/
}
return 0;
}
Below is the client code :
/************* UDP CLIENT CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]){
int clientSocket, portNum, nBytes, buflen;
char buffer[1024];
char string[1024];
struct sockaddr_in serverAddr,clientAddr;
socklen_t addr_size;
/*Create UDP socket*/
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum = atoi(argv[1]);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portNum);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");
// memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
memset(&serverAddr,0,sizeof(serverAddr));
// binding
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverAddr;
while(1){
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
//recvfrom(clientSocket,buffer,buflen,0,NULL,NULL);
printf("Received from server: %s\n",buffer);
/*
//********************************************************************
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
sendto(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr,addr_size);
printf("%s\n",buffer);
*/
}
return 0;
}
At a high level there are a few things that need to be addressed. Given the code in the post has a server that initiates communication with the client following line needs to be modified (and related code for these)
On the server side:
sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage,addr_size);
Essentially what's happening here is that udpSocket is bound to serverAddr and we are trying to sendto serverStorage (2nd last argument). The trouble here is that the serverStorage is not bound to anything. Basically sendto has the source right but not the destination.
On the client side:
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
The clientSocket is not bound to anything so the system picks a random port where it will listen. In the recvfrom call, 2nd last argument captures the address details of the other side. Whereas in the code you have bound it to server's IP and port, it does not have any effect because it is filled in by the recvfrom call and returned.
To make things work here is what I'd suggest (you can add the details but have worked out the skeleton based on what you posted)
server_initiating_with_client.c
//...
int udpSocket, nBytes, buflen;
char buffer[1024];
int portNum;
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
/*Create UDP socket*/
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum=atoi(argv[1]);
/*Configure settings in address struct*/
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5000); // Making sure server has a unique port number
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*Bind socket with address struct*/
int bStatus = bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (bStatus < 0) {
printf("error binding on server's port number\n");
exit(1);
}
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
/* Because server is initiating the communication here one needs to set the
* clientAddr and needs to know the port number of the client
*/
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum);
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
int bytesSent = sendto(udpSocket,buffer,buflen, 0,
(struct sockaddr *)&clientAddr,
sizeof(clientAddr));
if (bytesSent < 0) {
printf("Error sending/ communicating with client\n");
exit(1);
}
printf("Done sending %s\n", buffer);
sleep(1);
}
..
and on the client side something along these lines
//..
int clientSocket, portNum, nBytes, buflen;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
socklen_t addr_size;
/*Create UDP socket*/
clientSocket = socket(PF_INET, SOCK_DGRAM, 0);
portNum = atoi(argv[1]);
/*Configure settings in address struct*/
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum);
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&serverAddr, 0, sizeof(serverAddr));
/*Bind on client side as well because you are specifically sending something over
* to the client. Usually the server will know where to talk back to the client
* but in your example because of the reversed semantics this will be needed
*/
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverAddr;
while(1){
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
printf("Received from server: %s\n",buffer);
sleep(1);
}
return 0;
The code can be simplified if you reverse your comm from client to server, thereby, eliminating the need for a fixed port number on the client side.
just make a few changes in it. Assign a socket length predefined (socklen_t *) structure to typecast length
n = recvfrom(sockfd, (char *)buffer, MAXLINE,MSG_WAITALL, (struct sockaddr *) &servaddr, (socklen_t*)&len);
socklen_t* convert a length into socket length.
Make these changes at both client-side as well as a server-side
.

C: listen() API returning -1

I'm using below code to create a server program in c. The code is taken from here
#include <Winsock.h>
#include <string.h>
#include <ws2tcpip.h>
#include<conio.h>
int main(){
int welcomeSocket, newSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
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,5)==0)
printf("Listening\n");
else
printf("Error %d\n",listen(welcomeSocket,5));
/*---- 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 ----*/
strcpy(buffer,"Hello World\n");
send(newSocket,buffer,13,0);
getch();
return 0;
}
I've changed the code little bit to make it work in dev-c but in the output it's printing error i.e it's executing the else condition. Anyone have any idea why? And how to debug this?
I've tried changing the port no. It didn't work.
On Windows, you have to initialize the networking subsystem first by calling WSAStartup, before you can make any calls to socket/network-related functions.
WSADATA wsaData;
int wsaRc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (wsaRc != 0) {
fprintf(stderr, "WSAStartup failed with error: %d\n", wsaRc);
return 1;
}
/* Socket related functions callable from here on */
The example-code you've linked was written for UNIX systems, which do not have that API-requirement.
Please note, that you also
[...] must call the WSACleanup function for every successful
time the WSAStartup function is called.
(From the WSAStartup documentation).

C send function between server and client not working

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.

Resources