I'm writing in C and creating a Server that receives connections from multiple different Clients one at a time. However, after the first connection closes, the server can't be connected to again.
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
while(1) {
char server_message[256] = "You have reached the server!";
//Create a socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//Define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//Bind the socket to the IP and port
bind(server_socket, (struct sockaddr *) &server_address,
sizeof(server_address));
//Listen for connections
listen(server_socket, 5);
//Accept the connection
int client_socket = accept(server_socket, NULL, NULL);
//Send message
send(client_socket, server_message, sizeof(server_message), 0);
//Close the socket
close(server_socket);
}
return 0;
}
You're looping creating a server socket, accepting one connection, processing it, and then closing your server socket. The last action will throw away all pending connections. Your loop should start immediately after the listen() call and terminate after closing the client socket, and before closing the server socket.
You are also ignoring all errors on socket(), bind(), listen(), accept(), send(), and close(). Don't do that.
Change the code like this(omitted error checking):
int main() {
//Create a socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//Define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//Bind the socket to the IP and port
bind(server_socket, (struct sockaddr *) &server_address,
sizeof(server_address));
//Listen for connections
listen(server_socket, 5);
while(1) {
char server_message[256] = "You have reached the server!";
//Accept the connection
int client_socket = accept(server_socket, NULL, NULL);
/*check some condition to exit from loop*/
/*or send client to another thread for parallel programing*/
//Send message
send(client_socket, server_message, sizeof(server_message), 0);
//Close the client socket
close(client_socket);
}
close(server_socket);
return 0;
}
in this code server after get client must wait the client finished it's job and then try to accept new client, if you want parallel, accept client and data transfer in client, it's better to put client send and receive in another thread.
Related
I'm trying to really understand sockets, so I am learning it in C. This is the server code.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
char server_message[255] = "You have reached the server!";
//create server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//define server addr
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//Bind socket to IP and Port
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, 5);
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
//send message
send(client_socket, server_message, sizeof(server_message), 0);
//close socket
close(server_socket);
return 0;
}
In the bind function, this part is needed to specify the address
(struct sockaddr*) &server_address
I read the man page, and it does say it has to be this way, the code also runs, but I don't understand this syntax. What is happening in this part of the code. I know * is used to declare pointers, and & refers to the memory address of the variable. I just can't put it all together.
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
I found an RFID reader with a finger print reader that I would like to use. I tried to use sockets to listen to the port, but I'm unsure on how can I do it properly. The device does not have any labels, so I cannot find data from manufacturer on how to establish the connection. The devices works as I have tested with another software used for clocking in, so the device has now an IP address assigned that I'm able to ping. I have tried a socket server program to listen to the port, but I'm not getting anything when I read the RFID tags. How can I read data from the device when it is connected to the network and store the data?
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
main(){
char server_message[256] = "You have reached the server";
//create the server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//bind the socket to our specified IP and port
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
listen(server_socket, 5);
int client_socket;
client_socket = accept(server_socket,NULL,NULL);
char server_response[256];
recv(server_socket, &server_response, sizeof(server_response), 0);
//print out server's response
printf("The server sent the data: %s\n", server_response);
//send the message
send(client_socket, server_message, sizeof(server_message), 0);
//close the socket
close(server_socket);
return 0;
}
I want to make a TCP connection between my Virtual private server and my host machine using a TCP socket connection in C programming.
The serverside code is good and runs flawlessly.
Its the client side that only returns the string that the server is supposed to send out on the FIRST attempt of running it. After that the code doesnt work anymore and i have to restart my terminal and recompile the code for it to work again.
am i doing it right? did i call the IP of my vps right in my client.c?
This is my host machines client.c code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
// create a socket
int mySocket;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
//specify an address structure for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(666);
server_address.sin_addr.s_addr = inet_addr("IP OF MY VPS");
int connection_status = connect(mySocket, (struct sockaddr *) &server_address, sizeof(server_address));
//check for error with the connection
if (connection_status == -1) {
printf("There was an error making a connection to the remote socket \n\n");
exit(1);
}
// recieve data from the server
char server_response[256];
recv(mySocket, &server_response, sizeof(server_response), 0);
// pritn out the server's response
printf("The server sent the data: %s\n \n",server_response);
close(mySocket);
return 0;
}
Now here is the code for my VPS's server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
int main()
{
char server_message[256] = "client has connected";
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(666);
server_address.sin_addr.s_addr = INADDR_ANY;
bind(server_socket, (stuct sockaddr*) &server_address,
sizeof(server_address));
listen(server_socekt, 5);
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
send(client_socket, server_message,sizeof(server_message), 0);
close(server_socket);
return 0;
}
note: this code works some times but then most of the time it doesnt
You have no processing loop in the server: each time a client connects, after sending it a message, the server stops listening and terminates.
You can correct the problem in the server:
/* listen for new clients */
listen(server_socket, 5);
while (1)
{
int client_socket;
/* wait for a new client */
client_socket = accept(server_socket, NULL, NULL);
/* send the message */
send(client_socket, server_message,sizeof(server_message), 0);
/* and close only the client socket, not the listening one*/
close(client_socket);
}
/* Once the while loop is finished, you can stop listen (up to you to
change the while loop condition)*/
close(server_socket);
Another thing: you should use perror function to display errors messages, for instance,
int connection_status = connect(mySocket, (struct sockaddr *) &server_address, sizeof(server_address));
//check for error with the connection
if (connection_status == -1) {
perror("connect");
exit(1);
}
will give you this kind of message on error:
connect: Connection refused
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.