I tried to check if fopen returned a value < 0 but it does not. nad it sitll hangs in the same spot, strace gives me :
Code:
... , Writing to file now:
0xbfffdfc0, [16]) = ? ERESTARTSYS (To be restarted)
--- SIGCHLD (Child exited) ---
wait4(-1, NULL, 0, NULL) = 11491
sigreturn() = ? (mask now [])
accept(3,
here is my server code:
Code:
/*
** server.c -- a stream socket server demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <strings.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 <unistd.h>
#include "readline.c"
#include "readn.c"
#include "writen.c"
/* define port if needed */
#ifndef PORT
#define PORT 11000
#endif
/* max number of bytes we can get at once */
#define MAXDATASIZE (255)
/* how many pending connections queue will hold*/
#define BACKLOG (5)
void sigchld_handler(int s){
wait(NULL);
}
int main(void){
/* listen on sock_fd, new connection on new_fd*/
int sockfd, new_fd;
/* my address information */
struct sockaddr_in my_addr;
/* connector's address information */
struct sockaddr_in their_addr;
/* size of accept socket */
int sin_size;
/* used for child signaling */
struct sigaction sa;
FILE *log_file_in;
int numbytes;
/* input string from client */
char buf[MAXDATASIZE];
/* create the socket at sockfd, otherwise output error */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/* Make the socket reusable */
/* note: i had a problem that when i closed my server it would not let me start it
again right after because bind error: address already in use. So i did some
searching and learned about setsocketopt and the SO_REUSEADDR property
to solve the problem. */
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
/* host byte order */
my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(PORT);
/* automatically fill with my IP */
my_addr.sin_addr.s_addr = INADDR_ANY;
/* zero the rest of the struct */
bzero(&(my_addr.sin_zero), 8);
/* bind name: sockfd to my address, otherwise output error */
if (bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
/* listen on sockfd with a backlog, otherwise output error */
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
/* ?? */
sa.sa_handler = sigchld_handler; /* reap all dead processes */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
/* ?? */
/* main accept() loop*/
while(1) {
/* accept incoming connections, otherwise output error */
sin_size = sizeof(struct sockaddr_in);
printf("Calling accept...\n");
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
&sin_size)) == -1) {
perror("accept");
/* if an error occured then restart loop for new connection */
continue;
}
printf("completed accept\n");
/* ?? */
printf("server: got connection from %s\n",
inet_ntoa(their_addr.sin_addr));
/* ?? */
switch(fork()){
case 0:
/* child doesn't need the listener */
printf("Process %d; I am going to service the client.\n", getpid());
/* close listening socket since i am not listening */
close(sockfd);
printf("I am going to read from the client now.\n");
/* read max bytes and set numbytes to the amount read */
numbytes = Readn(new_fd, buf, MAXDATASIZE);
/* null terminate the string */
buf[numbytes] = '\0';
printf("Client said: %s", buf);
close(new_fd);
log_file_in = fopen("./log.txt","a");
if(log_file_in < 0){
perror("fopen");
}
printf("Writing to file now:\n");
fwrite(buf, 1, numbytes, log_file_in);
fclose(log_file_in);
printf("Process %d; my job is done.\n", getpid());
exit(0);
break;
case -1:
perror("fork error");
break;
default:
/* only parent gets here */
/* parent doesn't need this */
close(new_fd);
}
}
return 0;
}
here is client code
Code:
/*
** client.c -- a stream socket client demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <strings.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "readn.c"
#include "writen.c"
/* the port client will be connecting to */
#define PORT (11000)
/* max number of bytes we can get at once */
#define MAXDATASIZE (255)
int main(int argc, char *argv[]) {
/* socket for connection */
int sockfd;
/* used to determine amount of bytes read */
int numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
/* connector's address information */
struct sockaddr_in their_addr;
/* If there are not enough arguments output to stderr and halt */
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
/* get the host info, otherwise error */
if ((he=gethostbyname(argv[1])) == NULL) {
perror("gethostbyname");
exit(1);
}
/* create the socket, otherwise error */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/* host byte order */
their_addr.sin_family = AF_INET;
/* short, network byte order */
their_addr.sin_port = htons(PORT);
/* ?? */
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
/* ?? */
/* zero the rest of the struct */
bzero(&(their_addr.sin_zero), 8);
/* connect the socket, otherwise error */
if (connect(sockfd, (struct sockaddr *)&their_addr,
sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
Writen(sockfd, "Sup?\n", 5);
printf("I have written to the socket.\n");
/* close the socket */
close(sockfd);
return 0;
}
and here is the wrapper functions Readn and Writen
Readn
Code:
/* include readn */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
ssize_t
Readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ( (n = readn(fd, ptr, nbytes)) < 0)
perror("readn error");
return(n);
}
Writen
Code:
/* include writen */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
/* Write "n" bytes to a descriptor. */
ssize_t writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
/* keep writing until no more left to write */
while (nleft > 0) {
/* if i did not write anythign then chk if i got a interrupt signal and
so then retry write on the same byte ( do not increment pointer ) */
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (errno == EINTR)
/* and call write() again without moving to the next byte */
nwritten = 0;
else
/* another error occured */
return(-1);
}
/* decrease the number of written and move to next byte */
nleft -= nwritten;
ptr += nwritten;
}
/* return the number of writes */
return(n);
}
/* Error checked version of writen above */
void Writen(int fd, void *ptr, size_t nbytes)
{
if (writen(fd, ptr, nbytes) != nbytes)
perror("writen error");
}
thank you again