Orchestration for a simple server in C - c

I'm trying to make a simple multi-thread server in C, and I would like to make a queue for clients, so no one drops connection.
But I have no idea what to do and where to start.
Anyone can help? Any advices would be appreciated :)
and I had to remove the thread function code because code was too long that this question won't post.
int main(int argc, char const *argv[])
{
int server_fd, new_socket; //long valread;
struct sockaddr_in address;
int addrlen = sizeof(address);
pthread_t tid[1024];
int i = 0; // index for tid array
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("In socket");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
memset(address.sin_zero, '\0', sizeof address.sin_zero);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("In bind");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 10) < 0)
{
perror("In listen");
exit(EXIT_FAILURE);
}
while(1)
{
printf("\n+++++++ Waiting for new connection ++++++++\n\n");
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("In accept");
exit(EXIT_FAILURE);
}
if( pthread_create(&tid[i++], NULL, thread, &new_socket) != 0 )
printf("Failed to create thread\n");
if( i >= 1024 )
i = 0;
}
return 0;
}

Related

C socket successfully accept() but fails on recv()

I am trying to implement a server which accepts 2 connections one after another each of them sending data. My client-side can connect and fwrite successfully whereas my server-side connects successfully but fails to recv() anything. I have tried many things on the net but I could not resolve this. Why would recv() fail in this code after succesfully accepting and connecting on the socket?
Code of Server part —— Successful on accept() but fail on recv()
char** get_host_ip(){
char** arr = malloc(3* sizeof(char*));
int x;
for(x=0; x<3;x++){
arr[x] = malloc(256 *sizeof(char));
}
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
fd_set fdset;
struct timeval tv;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
//fcntl(socket_desc, F_SETFL, O_NONBLOCK);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
int reuse = 1;
if (setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEADDR) failed");
}
if(setsockopt(socket_desc, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEPORT) failed");
}
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
char* err = "Error on binding\r\n";
printf("%s\r\n",err);
}
puts("bind done");
//Listen
listen(socket_desc , 20);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
int k;
for(k=0; k<2; k++){
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if(client_sock < 0){
puts("Accept failed\r\n");
exit(0);
}
else{
puts("Accept succeeded");
}
if(k == 0) {
char* host_ip = inet_ntoa(client.sin_addr);
printf("IP address is: %s\n", inet_ntoa(client.sin_addr));
printf("port is: %d\n", (int) ntohs(client.sin_port));
strcpy(arr[k],host_ip);
int read_size = 0;
char readBuf[256];
if((read_size = recv(client_sock , readBuf , 256 , 0)) > 0){
printf("readBuf: %s\r\n",readBuf);
strcpy(arr[k+1],readBuf);
memset(readBuf,0,256);
}
else{
printf("Receive has failed.. read_size: %d\r\n",read_size);
}
}
else {
int read_size;
char readBuf[256];
if((read_size = recv(client_sock , readBuf , 256 , 0)) > 0){
printf("readBuf: %s\r\n",readBuf);
strcpy(arr[k+2],readBuf);
memset(readBuf,0,256);
}
else{
printf("Receive has failed.. read_size: %d\r\n",read_size);
}
}
}
close(client_sock);
close(socket_desc);
return arr;
}
Client part —— connect() and fwrite() successful
void give_envi(char* env_var) {
printf("The environment variable sent: %s\r\n",env_var);
int receive_no = 1;
int sock;
struct sockaddr_in server;
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
//puts("Socket created");
//char host_ip[20];
//strcpy(host_ip,getenv("HOST_IP"));
server.sin_addr.s_addr = inet_addr("127.0.0.1"); //PROVIDE THE IP OF THE TARGET TO SEND YOUR DATA.
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );
int reuse = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEADDR) failed");
}
if(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int)) < 0){
perror("setsockopt(SO_REUSEPORT) failed");
}
//Connect to remote server
if ( connect(sock , (struct sockaddr *)&server , sizeof(server)) > -1) {
puts("Connection established!\r\n");
}
else{
puts("Connection failed\r\n");
}
FILE * file = fdopen(sock, "w");
if(fwrite (env_var ,sizeof(char), strlen(env_var), file) == strlen(env_var)){
printf("fwrite() SUCCESS\r\n");
}
else{
printf("FAILED on fwrite()\r\n");
}
close(sock);
}

How to send a message from server to client in C

Hey guys I want to send a message of the current date from the server to a client in C.
So I would use a command like this for the client;
Terminal
telnet localhost PORT
What should be the command to send the actual message?
int main(int argc, char *argv[])
{
int socket_desc, client_sock, c, read_size;
struct sockaddr_in server, client;
char client_message[2000];
time_t t = time(NULL);
struct tm tm = *localtime(&t);
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
listen(socket_desc, 3);
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
puts("Connection accepted");
////////////////////////////////////////////////////
//the actual message here
////////////////////////////////////////////////////
close(socket_desc);
return 0;
}
I made the following addiction and it worked
Is this a proper solution? I don't know how to use send() properly yet.
pid_t child_pid = fork();
if (child_pid == 0)
{
snprintf(client_message, sizeof(client_message), "%s", ctime(&tick));
write(client_sock, client_message, strlen(client_message));
shutdown(client_sock, SHUT_RDWR);
while (read(client_sock, client_message, sizeof(client_message) > 0))
close(client_sock);
}
else if (child_pid > 0)
{
// parent
close(client_sock);
}
else
{
// a fork error occurred, handle and remember to close(connfd)
}

Sending command line arguments from client to server

I want to input arguments from the command line to the client and make the server receive them and print them.
current codes:
Client:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define PORT 8080
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf(Invalid address\n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("Connection Failed \n");
return -1;
}
if(argc>=2){
int i, numb;
for(i=0; i<argc; i++) {
send(sock , &argv[i] , 10000 , 0 );
}
}
return 0;
}
Server:
#define PORT 8080
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read( new_socket , buffer, 1024);
puts("The client sent the values: ");
if(argc>=2){
int i;
for(i=0; i<argc; i++) {
int* valuerec=(int *)buffer;
int val2=*valuerec;
printf("%d\n", val2);
puts(" ");
}
}
return 0;
}
I tried doing it multiple ways such as using atoi before sending but all resulted in no output of numbers, any help on how I can establish this?
I am aware I didn't include the server libraries in this post but that is just to make it shorter.

The second connection in two-client socket program is rarely not accepted from the server

I am new to socket programming, so I'm sorry if this is a noob question.
I have a program in C for Linux, which connects two sockets from "server.c" to two "client.c"s with the help of fork(). It works just fine most of the time, but there are times when the second client gets stuck before the first recv() function. On these occasions, the server doesn't accept() the connection and I am confused as to what is truly happening and how I can fix it.
Since I don't know much about socket programming, any explanation could be useful.
Here is the codes for the server and the client:
server.c
int main(){
int server_socket, p1_socket, p2_socket;
int pid;
pid = fork();
if(pid<0)
printf("Fork failed.\n");
else if(pid==0){
//PLAYER 1
socket_creation_and_connection(&server_socket, &p1_socket);
connect_to_player(&p1_socket, 1);
}
else{
//PLAYER 2
socket_creation_and_connection(&server_socket, &p2_socket);
connect_to_player(&p2_socket, 2);
}
printf("Hello message sent from %d\n", pid);
return 0;
}
void connect_to_player(int *socket, int playerNo){
char buffer[256];
while(1){
send(*socket , (int *)&playerNo , sizeof(int) , 0);
recv(*socket, (int *)&buffer, 1024, 0);
printf("PlayerNo %d Message received from client %s\n", playerNo, buffer);
}
}
void socket_creation_and_connection (int *server_socket, int *new_socket){
struct sockaddr_in address;
int addrlen = sizeof(address);
printf("creating sth\n");
if ((*server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0){
perror("Failed to create socket.");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(*server_socket, (struct sockaddr *)&address, sizeof(address))<0){
perror("Failed to bind.");
exit(EXIT_FAILURE);
}
if (listen(*server_socket, 3)<0){
perror("Failed to listen.");
exit(EXIT_FAILURE);
}
if ((*new_socket = accept(*server_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0){
perror("Failed to accept.");
exit(EXIT_FAILURE);
}
printf("finished creating sth\n");
}
client.c
int main(){
int client_socket = 0;
char message[256];
socket_creation_and_connection(&client_socket);
int intbuf;
while(1){
recv(client_socket, (int *)&intbuf, sizeof(int), 0);
if(intbuf == 1)
printf("Received message from Player1\n");
else
printf("Received message from Player2\n");
printf("Type a string\n");
scanf("%s", message);
send(client_socket, message , strlen(message) , 0 );
sleep(1);
}
return 0;
}
void socket_creation_and_connection(int *client_socket){
struct sockaddr_in address;
if ((*client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
if (connect(*client_socket, (struct sockaddr *)&address, sizeof(address)) < 0)
{
printf("Connection Failed.\n");
exit(EXIT_FAILURE);
}
}
Edit: PORT is defined along with the libraries like this.
#define PORT 8080

Connection Refused even after adding a new Firewall rule

I am trying to connect to my local UNIX server i made from another remote device. the Server is up and listening to the port i specified. i also added a new firewall rule to open that port but still my client cannot connect. it shows ERROR CONNECTION REFUSED
here is my server code
int main() {
int fd, i,svclient,rval,msg;
int clients[10], num_clients;
fd_set read_set,write_set;
char buf[100];
struct sockaddr_in addr;
if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(4001);
//strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
//strcpy(addr.sun_path, NAME);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
exit(-1);
}
printf("Bind complet...\n");
if (listen(fd, 20) == -1) {
perror("listen error");
exit(-1);
}
num_clients = 0;
int size = sizeof(fd);
while (1) {
int clientfd;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
for (i = 0; i < num_clients; i++) { //at first this part will not excute
FD_SET(clients[i], &read_set);
}
select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(fd, &read_set)) {
if ( (clients[num_clients++] = accept(fd,(struct sockaddr*)&client_addr,&addrlen)) == -1) {
perror("accept error");
continue;
}
/*printf("incoming message..................... !\n \n");*/
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
for (i = 0; i < num_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
msg = read(clients[i], buf, sizeof(buf));
if(msg > 0){
buf[msg] = 0;
int savedclnt = clients[i];
printf("%s \n \n", buf);
/*for(int p=0;p<num_clients;p++)
{
if( clients[p]!= savedclnt){
write(clients[p],buf,msg);
}
}*/
}
}
}
}
}
and my client
int main( )
{
struct uci_context *uci;
uci = uci_init();
int sockfd;
int ret;
struct sockaddr_in dest;
struct addrinfo hint, *res = NULL;
struct hostent *host;
char *hostip;
char *string;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
puts("Unble to create socket");
exit(1);
}
hostip = ucix_get_option(uci, "pack_mon", "pack_monitoring", "address");
string = ucix_get_option(uci, "pack_mon", "pack_monitoring", "port");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(string));
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
printf(" %s- %s\n", hostip, string );
if(isdigit(hostip[0])){
ret = getaddrinfo(hostip, NULL, &hint, &res);// this is more efficient than inet_addr
if (ret) {
exit(1);
}
}else if( (host = gethostbyname(hostip)) != 0){
memcpy((char*)&dest.sin_addr , (char*)host->h_addr , (sizeof dest.sin_addr)+1);
}else{
exit(1);
printf("cannot resolve ip address");
}
if ( connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0 )
{
perror("ERROR Connecting" );
exit(1);
}else{
printf("Port number %s is open.....\n",string);
}
char *message;
message = "help";
write(sockfd,message,strlen(message));
close(sockfd);
freeaddrinfo(res);
return 0;
}
FIREWALL RULE
sudo iptables -I INPUT -p tcp --dport 4001 -j ACCEPT
Error is :
192.168.10.155- 4001
ERROR Connecting: Connection refused
and this logs are coming from this codes :
printf(" %s- %s\n", hostip, string );
perror("ERROR Connecting");
exit(1);
Your client has no code to specify the IP address it wants to connect to. All the code that could do that has been commented out.
Update: Now your bug is here:
strncpy((char*)&dest.sin_addr , (char*)host->h_addr , sizeof dest.sin_addr);
The strncpy function is only suitable for C-style strings. You need to use memcpy or something similar. This will only copy part of the IP address if any octet other than its last one (in network byte order) is zero.
Update: Now your bug is here:
printf("%d\n", connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0);
perror("hmmmm" );
exit(1);
This calls connect, then calls printf and then calls perror. The problem is, the call to printf can modify errno even if it succeeds. Thus your call to perror can print a totally irrelevant error message.

Resources