C structs help - I'm lost / BSD sockets - c

I'm a newbie to C and am a little lost.
So what am I doing?
A multi-threaded web server.
What I'm trying to do?
To pass a struct with data to the threaded function.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_fw.h>
#include <pthread.h>
#define MYPORT 8080
#define BACKLOG 36600
struct thread_data {
int new_fd;
struct address_data adata;
};
struct address_data {
unsigned long s_addr;
};
//---------------------------httpRequest Method------------------------
void* httpRequest(void* data)
{
struct thread_data me;
me = *((struct thread_data*)data);
printf("struct ip: %s\n", inet_ntoa(me.adata));
printf("struct fd: %d\n", me.new_fd);
pthread_exit(NULL); //Existing from the threads.
}
//****************************************************************************************************************
//Main Method------------------------------------------------------------------
int main (void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
struct thread_data td;
int sin_size;
struct sigaction sa;
int yes=1;
pthread_t p_thread[3000];
int thr_id,i=0;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
// bzero((char *) &my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // read all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
while(1)
{ // main accept() loop
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,&sin_size)) == -1) {
perror("accept");
continue;
}
printf("Got connection from %s\n",inet_ntoa(their_addr.sin_addr));
td.new_fd = (int *)&new_fd;
td.adata = their_addr.sin_addr;
//Creates threads.
thr_id = pthread_create(&p_thread[i++],NULL,httpRequest,(void*)&td);
}
return 0;
}
When I get a connection, the program unexpectedly exits.
As you can see I've made the thread_data struct as a model to sockaddr_in. It'd be great, if you could point out where I'm going wrong. Thanks in advance.

There are probably other errors. But at the very least:
int main (void)
{
struct thread_data td;
while(1)
{
thr_id = pthread_create(&p_thread[i++],NULL,httpRequest,(void*)&td);
}
return 0;
}
You have only one copy of td. Yet you pass the same one to multiple threads. So on the second request, you overwrite the same td you gave to the first thread.

Related

concurrent server threads - giving binding error

I am trying to create two threads that can listen at two different ports.
My logic is:
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdbool.h>
typedef struct server_arg {
int portNum;
} server_arg;
void *server_socket_creation(void *arg) {
server_arg *s = (server_arg*)arg;
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0))
== 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
int enable = 1;
if(setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&enable,sizeof(int)) < 0) {
perror("error");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(s->portNum);
if (bind(server_fd, (struct sockaddr*)&address,
sizeof(address))
< 0) {
perror("bind failed");
}
if (listen(server_fd, 3) < 0) {
perror("listen");
}
if ((new_socket
= accept(server_fd, (struct sockaddr*)&address,
(socklen_t*)&addrlen))
< 0) {
perror("accept");
}
printf("Server Connected\n");
}
int main(int argc, char const* argv[])
{
server_arg *s = (server_arg*)malloc(sizeof(server_arg));
pthread_t id_1;
pthread_t id_2;
s->portNum = htons(9191);
pthread_create(&id_1,NULL,(void *)server_socket_creation,(void *)s);
s->portNum = htons(6123);
pthread_create(&id_2,NULL,(void *)server_socket_creation,(void *)s);
pthread_detach(id_1);
pthread_detach(id_2);
pthread_exit(0);
}
error: binding error: Address Already in use
Now, after searching about this issue on stackoverflow:
I could find 2 reasons:
Ports are already in use. (Means using same ports in this case)
which is not the case here as you can see.
server IP address is same.
I think this is the issue here, but I can't think of any way to solve this.
You have a single server_arg structure. You pass a pointer to this single server_arg structure to both threads.
There's a very significantly large chance that the assignment
s->portNum = htons(6123);
will happen before the first thread have copied the value with
address.sin_port = htons(s->portNum);
This is what is called a data-race. And as any data-race, the only looser is you as the programmer.
You need two structures, one for each thread. For example as an array:
server_arg s[2[ = {
{ 9191 },
{ 6123 }
};
Then pass &s[0] to the first thread, and &s[1] to the second.
There's also another problem with the port number, which should be quite easily seen when you put both the port assignments close to each other like I did above: You call htons twice.

Check if UDP port is open with ICMP in C

I am trying to check if a specific UDP port is open or not. I am trying to do this by sending UDP packets and checking the ICMP response to see if the UDP port is avaiable or not. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <arpa/inet.h> /* inet(3) functions */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdio.h>
#include <errno.h>
#define MAXLINE 10096
int main(int argc, char **argv)
{
int sockfd, portno;
struct sockaddr_in servaddr;
struct hostent *server;
int sendfd, recvfd;
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr,"ERROR, no such host\n");
exit(EXIT_FAILURE);
}
//socket varibles
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&servaddr.sin_addr.s_addr, server->h_length);
//get port from command line arguments
portno = atoi(argv[2]);
servaddr.sin_port = htons(portno);
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
// open send UDP socket
if((sendfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
perror("*** socket(,,IPPROTO_UDP) failed ***n");
exit(-1);
}
// open receive ICMP socket
if((recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("*** socket(,,IPPROTO_ICMP) failed ***n");
exit(-1);
}
int n;
char sendline[] = "a message"; //string for message to be sent
char recvline[MAXLINE]; //string for message to be received
//send ping request
if(sendto(sendfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
{
perror("*** sendto() failed ***");
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 100000;
if (setsockopt(recvfd, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0) {
perror("Error");
}
n = recvfrom(recvfd, recvline, MAXLINE, 0, NULL, NULL);
recvline[n] = '\0'; /* null terminate */
struct iphdr *ip_hdr = (struct iphdr *)recvline;
int iplen = ip_hdr->ihl << 2;
struct icmphdr *icmp = (struct icmphdr *)((char *)ip_hdr + (4 * ip_hdr->ihl));
if((icmp->type == ICMP_UNREACH) && (icmp->code == ICMP_UNREACH_PORT))
{
printf("\nPORT CLOSED\n");
}
else
{
printf("\nPORT OPEN\n");
}
exit(0);
}
How can I get this working? When I run the code, It always says "PORT OPEN" in every port I test it with which definitely cannot be right.

Multithread server client C

Hello i have some problem with threads and client and server implementation, i created 2 clients that write on the socket infinite numbers.
to managed the 2 client in the sever.c i create threads everytime a new connection is accept.
it runs but if one client run it works but if i run the second one the first interrupted itself; how can i printf alternately ?
i would like : G1
G2
G1 etc
G1.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
struct message { //dichiarazione struct
time_t timestamp;
char g; //process identifier
int x;
};
int main(int argc, char *argv[])
{
int sockfd, portno, n,i;
struct message m1;
struct sockaddr_in serv_addr;
struct hostent *server;
struct timespec delay;
delay.tv_sec = 1;
delay.tv_nsec = 0; //in microseconds
long int offset=1000000;
struct timeval tv;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_UNIX;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
while(1){
m1.timestamp=time(NULL);
m1.x=i;
m1.g=getpid();
n = write(sockfd,&m1,sizeof(m1));
if (n < 0)
error("ERROR writing to socket");
i++;
delay.tv_nsec=offset+rand()%offset;
nanosleep(&delay,NULL);
}
return 0;
}`
R.c(server)
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include <arpa/inet.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include<pthread.h>
struct message { //dichiarazione struct
time_t timestamp;
char g; //process identifier
int x;
};
struct message client_message;
char buffer[1024];
static void * socketThread(void *arg)
{
while(1) {
int newSocket = *((int *)arg);
recv(newSocket , &client_message , sizeof(client_message), 0);
printf("message %d %d %ld\n",client_message.x,client_message.g,client_message.timestamp);
fflush(stdout);
sleep(1);
}
}
int main(){
int serverSocket, newSocket;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
//Create the socket.
serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
// Configure settings of the server address struct
// Address family = Internet
serverAddr.sin_family = AF_UNIX;
//Set port number, using htons function to use proper byte order
serverAddr.sin_port = htons(6005);
//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(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
//Listen on the socket, with 40 max connection requests queued
if(listen(serverSocket,50)!=0)
{
printf("Error\n");
return -1;
}
printf("Listening\n");
pthread_t tid[60];
int i = 0;
while(1)
{
//Accept call creates a new socket for the incoming connection
addr_size = sizeof serverStorage;
newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
//for each client request creates a thread and assign the client request to it to process
//so the main thread can entertain next request
if( pthread_create(&tid[i], NULL, socketThread, &newSocket) != 0 )
printf("Failed to create thread\n");
else
++i;
}
return 0;
}
Thanks !
As I understand in server code in thread function socketThread() you get value of socket descriptor on each iteration. But when you accept new connection in this address writes new value of new socket descriptor. And after that each thread gets data only from last socket.
You should pass in socketThread() socket descriptor by value (not by a pointer)!

How to count time in socket

I have a simple server-client program which acts according to the received data from client.
When the received data is string start I want the server to count time in seconds until it receives stop command from client, and as server receives stop server sends back counted seconds to the client.
I'm new in C programming and I don't know how to use time.h library. I have tried to use some commands, but got few errors.
/* tcpserver.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/sysinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "address.h"
int main() {
int sock, connected, bytes_recieved , true = 1, number;
char send_data [1024] , recv_data[1024];
struct sockaddr_in server_addr,client_addr;
struct sysinfo info;
int sin_size;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {
perror("Setsockopt");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(1237);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))
== -1) {
perror("Unable to bind");
exit(1);
}
if (listen(sock, 5) == -1) {
perror("Listen");
exit(1);
}
printf ("\nTCPServer Waiting for client on port 1237");
fflush(stdout);
number = 0;
while(1) {
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
printf("\n I got a connection from (%s , %d)",
inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
send(connected, "Hello, this is simple program.", 100, 1);
while (1) {
printf("\n SEND (q or Q to quit) : ");
fgets(send_data, sizeof(send_data), stdin);
bytes_recieved = recv(connected,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
if (strcmp(favoriteDairyProduct, "start") == 0 || strcmp(favoriteDairyProduct, "START") == 0) {
// count the time until stop is recieved
}
printf("\n RECIEVED DATA = %s " , recv_data);
fflush(stdout);
send(connected, send_data,strlen(send_data), 0);
}
}
close(sock);
return 0;
}
Here is the client code. One other thing I would like to do is to change the program to receive multiple clients. But for now timer is more important.
/* tcpclient.c */
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/sysinfo.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "address.h"
#include <time.h>
int main()
{
int sock, bytes_recieved, number;
char send_data[1024],recv_data[1024];
struct hostent *host;
struct sockaddr_in server_addr;
struct sysinfo info;
host = gethostbyname("127.0.0.1");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(1237);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
perror("Connect");
exit(1);
}
while(1) {
bytes_recieved = recv(sock,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
printf("\nRecieved data = %s " , recv_data);
printf("\nSEND (q or Q to quit) : ");
fgets(send_data, sizeof(send_data), stdin);
send(sock,send_data, sizeof(send_data), 0);
}
close(sock);
return 0;
}
Depending on the platform you are on, you could use gettimeofday() when you receive both the start and stop messages.
#include <sys/time.h>
struct timeval t1, t2;
if (<received start command>) {
gettimeofday(&t1, NULL);
}
if (<received stop command>) {
gettimeofday(&t2, NULL);
}
Each gives you the current time in seconds and microseconds. You have to find the difference between the two.
time_t diff_sec = t2.tv_sec - t1.tv_sec;
suseconds_t diff_usec = t2.tv_usec - t1.tv_usec;
Of course you have to take into account that t2.tv_usec could be smaller than t1.tv_usec.
You should also verify that you have received a start before a stop, or the results won't make sense.
I'll leave the rest as an exercise to the reader since this looks like homework.

when does poll() return POLLERR

server.c -> always recv client data(use poll() to confirm whether an error occurred)
client.c -> always send data to server
I exec server.c and client.c ,then i try to kill client.c process.
But the POLLERR flag never be set.
The man page only say
POLLERR Error condition (output only)
When does Poll() return POLLERR?
What did I miss?
Thanks.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
int main()
{
int rc = 0;
char str[100];
char test[5];
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
struct pollfd fds[200];
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(22000);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
fds[0].fd = comm_fd;
fds[0].events = POLLIN | POLLOUT | POLLERR | POLLHUP;
printf("start\n");
while(1) {
rc = poll(fds,1,1000);
if (rc < 0)
printf("failed\n");
else if(rc==0)
printf("timeout\n");
else {
if (fds[0].revents & POLLERR){
printf("Error!!\n");
}
if(fds[0].revents & POLLHUP){
printf("handup!!\n");
break;
}
if (fds[0].revents & POLLIN){
int bl = recv(comm_fd,test,4,0);
printf("recv:%s %d\n",test,bl);
}
}
sleep(1);
}
return 0;
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
int main(int argc,char **argv)
{
int sockfd,n;
char sendline[100];
char recvline[100];
struct sockaddr_in servaddr;
sockfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof servaddr);
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(22000);
inet_pton(AF_INET,"127.0.0.1",&(servaddr.sin_addr));
connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
while(1){
send(sockfd,"test",4,0);
sleep(5);
}
close(sockfd);
return 0;
}
It's implementation dependent. Most applications just treat POLLERR the same as normal readiness, allowing the subsequent operation to fail.

Resources