How to count time in socket - c

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.

Related

C socket : connect error - invalid argument

I made a simple Process-based parallel socket program.
My client code reaches the connect part and throws an Invalid argument error, and my server doesn't ouput anything. just cursor...
I split the terminal in two to run the code.
I run the code with:
gcc -o p-server p-server.c -Wall
./p-server
gcc -o p-client p-client.c -Wall
The output is
[C] Connecting...
[C] Can't connect to a Server: Invalid argument
p-server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
//#include <sys/wait.h>
#define BUFFSIZE 4096
#define SERVERPORT 7799
int main(void){
int i, j, s_sock, c_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t c_addr_size;
char buf[BUFFSIZE] = {0};
char hello[] = "Hello~ I am Server!\n";
//int option = 1;
//setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVERPORT);
server_addr.sin_addr.s_addr = inet_addr("10.0.0.131");
s_sock = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
perror("[S] Can't bind a socket");
exit(1);
}
if(listen(s_sock, 5)) {
perror("[S] Can't listen");
exit(1);
}
c_addr_size = sizeof(client_addr);
for ( i=0; i<3; i++) {
if ((c_sock = accept(s_sock, (struct sockaddr *) &client_addr, sizeof(client_addr))) == -1 ){
perror("[S] Can't accept a connection");
exit(1);
}
printf("[S] Connected: client IP addr=%s port=%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
//fork
switch(fork()){
case 0:
close(s_sock);
//1. say hello to client
if(send(c_sock, hello, sizeof(hello)+1, 0) == -1) {
perror("[S] Can't send message");
exit(1);
}
printf("[S] I said Hello to Client!\n");
//2. recv msg from client
if(recv(c_sock, buf, BUFFSIZE, 0) == -1) {
perror("[S] Can't receive message");
exit(1);
}
printf("[S] Client says: %s\n", buf);
exit(0);
}
close(c_sock);
}
/*
for(j=0; j<3; j++){
wait(&status);
printf("Patren waits %d\n"), wstatus;
}*/
}
p-client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFSIZE 4096
#define SERVERPORT 7799
int main(void){
int c_sock;
struct sockaddr_in server_addr;
socklen_t c_addr_size;
char buf[BUFFSIZE] = {0};
char hello[] = "Hi~I am Client!\n";
if((c_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVERPORT);
server_addr.sin_addr.s_addr = inet_addr("10.0.0.131");
printf("[C] Connecting...\n");
if (connect(c_sock, (struct sockaddr *) &server_addr, sizeof(server_addr) == -1)) {
perror("[C] Can't connect to a Server");
exit(1);
}
printf("[C] connected!\n");
//1. recv msg from server (maybe it's "hello")
if (recv(c_sock, buf, BUFFSIZE, 0) == -1) {
perror("[C] Can't receive message");
exit(1);
}
printf("[C] Server says: %s\n", buf);
//2. say hi to server
if(send(c_sock, hello, sizeof(hello)+1, 0) == -1) {
perror("[C] Can't send message");
exit(1);
}
printf("[C] I said Hi to Server!!\n");
printf("[C] I am going to sleep...\n");
sleep(10);
close(c_sock);
return 0;
}

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.

SIGIO never fires

ioctl() with changes a socket to asynchronous mode. By the definition on the man page, the kernel sends SIGIO when i/o is possible on the socket. I've run this with test clients and i/o is fine (packets arrive at source and destination), so why wouldn't the kernel call sigpoll?
To clarify, the problem is that despite having established the SIGIO signal and appropriating the socket to send the signal SIGIO, no signal ever fires or there is no indication that sigpoll() was called.
I've uploaded the code where I've found this issue, it will eventually be some watered down version of talk.
talkish.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#define MAX_BUF 1000
#define CHAR_BUF 50
#define BASEPORT "10000"
void error(const char *msg){
perror(msg);
exit(1);
}
typedef struct tuple{
char HN [MAX_BUF];
char PN [MAX_BUF];
}tuple;
tuple storeCMD( char input[]){
tuple ret;
char* token = strtok(input, " ");
if (token != NULL) strcpy( ret.HN, token);
else ret.HN[0] = 0;
token = strtok(NULL, " ");
if (token != NULL) strcpy( ret.PN, token);
else ret.PN[0] = 0;
return ret;
}
void sigpoll(int sig){
printf("Signal fired!\n");
//eventual rcvfrom and other things...
}
int main(int argc, char * argv[]){
if (argc != 2){
printf("Proper usage requires 2 arguments: $talkish port-number\n");
exit(1);
}
int sd;
struct sockaddr_storage client;
socklen_t clientLen;
struct addrinfo server, *res;
struct addrinfo *serverinfo;
char buffer [MAX_BUF];
memset(&server, 0, sizeof(server));
bzero((char *) &server, sizeof(server));
server.ai_family = AF_INET;
server.ai_socktype = SOCK_DGRAM;
server.ai_flags = AI_PASSIVE;
//initially we'll use information from user, but move to partner and partnerl
//once solid connection is established.
struct sockaddr_storage partner;
socklen_t partnerl;
//Bind to argv[1]
tuple execute;
getaddrinfo(NULL, argv[1], &server, &res);
sd = socket(res -> ai_family ,res -> ai_socktype, res -> ai_protocol);
if (sd < 0) error("ERROR on socket!");
int n = bind(sd, res -> ai_addr, res -> ai_addrlen);
if (n < 0) error("ERROR on Bind!");
int flag;
flag= 1;
fcntl(sd, F_SETOWN, getpid());
signal(SIGPOLL, sigpoll); //establish sigpoll to get udp packets
ioctl(sd, FIOASYNC, &flag);
//establish timer to allow wait and see
struct timeval timer;
timer.tv_sec = 7;
//while connecting
char message[CHAR_BUF];
bzero((char *) message, CHAR_BUF);
int connecting = 1;
while(connecting){
printf ("? ");
scanf(" %[^\n]", message);
if (strlen(message) == 0);
else if ( 0 == strcmp( message, "q")){
exit (0);
}
else {
execute = storeCMD(message);
if (execute.HN[0] == 0 || execute.PN[0] == 0) printf("| Input should match \"Hostname Portname\" to connect and \"q\" to quit \n");
else {
struct sockaddr_storage dest_server;
socklen_t dest_serverl;
struct addrinfo dest_hints, *dest_res;
struct in_addr dest_addr;
memset(&dest_hints, 0, sizeof(dest_hints));
dest_hints.ai_family = AF_INET;
dest_hints.ai_socktype = SOCK_DGRAM;
dest_hints.ai_flags = AI_PASSIVE;
if (getaddrinfo( execute.HN, execute.PN, &dest_hints, &dest_res) < 0) printf("| Input should match \"Hostname Portname\" to connect and \"q\" to quit \n");
else {
bzero((char *) buffer, MAX_BUF);
sprintf(buffer, "wannachat");
sendto(sd, buffer, MAX_BUF, 0, (struct sockaddr *) dest_res -> ai_addr, dest_res -> ai_addrlen );
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer)) < 0) error("ERROR on setsockopt");
partnerl = sizeof(partner);
bzero((char *) &partner, partnerl);
bzero((char *) buffer, MAX_BUF);
if (recvfrom(sd, buffer, MAX_BUF, 0, (struct sockaddr *)&partner, &partnerl ) < 0) printf("| No response received from %s. \n", execute.HN);
else{
if ( 0 == strcmp( buffer, "OK")){
printf("| Connected to %s. \n", execute.HN);
//chat();
}else printf("| %s does not want to talk. \n", execute.HN);
}
}
}
}
}
close(sd);
return 0;
}
To receive SIGIO notifications (also SIGURG for sockets, e.g: when receiving TCP URG data), you'll need to tell the kernel who to notify, using fcntl(fd, F_SETOWN, pid). As usual, a positive pid value refers to a process, while a negative pid refers to a process group.
On Linux, if you want to send the signal to a specific thread, you'll need to use F_SETOWN_EX. On other systems, you'll have to block the signal on other threads. using pthread_sigmask().

bzero in socket programming

I am writing a simple client/server chat program in c. I am not understanding why one program works and the other doesn't. The programs given for client and server which are working are below. When I replace bzero(&(server.sin_zero),8) with bzero((char*)server,sizeof(server)) in both codes, it throws an error that "transport endpoint is not connected". They have implemneted using the second method and it works at this site.
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
struct sockaddr_in server;
int s1;
char message[500];
server.sin_port = htons(5000);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
bzero(&(server.sin_zero),8);
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(connect(s1,(struct sockaddr *)&server,sizeof(server)) == -1) {
perror("not able to connect\n");
exit(1);
}
int n = read(s1,message,500);
if(n < 0) {
perror("message not recieved\n");
exit(1);
}
printf("%s\n",message);
close(s1);
return 0;
}
Here is the program for the server.
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
struct sockaddr_in server,client;
int s1,s2,len;
char message[500];
server.sin_port = htons(5000);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
bzero(&(server.sin_zero),8);
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
printf("connected");
if(s2 == -1) {
perror("unable to accept connection");
exit(1);
}
strcpy(message,"you are connected");
message[strlen(message)] = '\0';
int n = write(s2,message,strlen(message));
if(n < 0) {
perror("message not sent\n");
exit(1);
}
close(s1);
close(s2);
return 0;
}
bzero(&(server.sin_zero),8)
only zeroes out the sin_zero array.
bzero((char*)server,sizeof(server))
on the other hand, zeroes out the whole struct, thus resetting the values you set before (like sin_port).
Finally, first zero out the struct, then initialize it (just like they did it on the site you referred to; pay attention to the details :-)).

Client can't receive messages from server?

I'm writing 2 small test programs in C (client/server) and I'm having trouble sending messages from the server to the client (but the other way around works just fine). The server says it sent 20 bytes, but on the client's end it says "failed to receive data". I would appreciate any help, thank you so much! My code is below:
Server:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc, char* argv[])
{
int sockfd, client_sockfd;
struct sockaddr_in server;
int reading, fileSize;
int i; //counter
int bytesSent;
char test[20] = "test message\n";
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1])); //assign port to listen to
server.sin_addr.s_addr = INADDR_ANY; //IP address
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) //create socket failed
{
perror("socket");
exit(1);
}
if(bind(sockfd, (struct sockaddr *) &server, sizeof(server)) == -1) //connect server socket to specified port
{
perror("bind call failed");
exit(1);
}
//printf("listening to port %d\n", server.sin_port);
if(listen(sockfd, 5) == -1) //queue size of 5
{
perror("listen call failed");
exit(1);
}
while(1) //infinite loop to process connections from clients
{
client_sockfd = accept(sockfd, NULL, NULL); //accept anything
if(client_sockfd == -1)
perror("accept call failed");
bytesSent = send(client_sockfd, test, 20, 0);
printf("bytes sent: %d\n", bytesSent);
}
close(client_sockfd);
close(sockfd);
return 0;
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char* argv[])
{
int sockfd;
struct sockaddr_in server;
struct hostent *server_ip_address;
server_ip_address = gethostbyname("eos-class.engr.oregonstate.edu");
int sent; //number of bytes sent
int received; //number of bytes received
char passedMsg[20]; //holds received message
if(server_ip_address == NULL)
{
fprintf(stderr, "could not resolve server host name\n");
exit(1);
}
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[3])); //assign port to connect to
memcpy(&server.sin_addr, server_ip_address->h_addr, server_ip_address->h_length);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) //create socket failed
{
perror("socket");
exit(1);
}
if(connect(sockfd, (struct sockaddr *) &server, sizeof(server)) == -1) //connect socket to remote address failed
{
printf("tried to connect to port %d\n", server.sin_port);
perror("connect");
exit(1);
}
if((received = recv(sockfd, passedMsg, 20, 0)) < 0);
{
printf("Failed to receive data\n");
exit(1);
}
printf("Received message: %s\n", passedMsg);
close(sockfd);
return 0;
}
In your client code, in the error checking for recv, change printf to perror. If you do, the output will be:
Failed to receive data: Success
So the recv call was successful, but the error code ran anyway. Why? Let's take a closer look at that if statement:
// what's this? ----v
if((received = recv(sockfd, passedMsg, 20, 0)) < 0);
{
printf("Failed to receive data\n");
exit(1);
}
There's a stray ; after the condition in the if statement. This means that the if statement does nothing if the condition is true, and that the following block is not the body of the if but an independent block that always runs.
Get rid of the extra ; and you get the expected results.

Resources