Socket: process dies after binding a new socket - c

I'm writing an ftp server in C using fork() to handle multiple client. The
create part and bind part are as follows:
//create socket
int createSocket()
{
int listenfd;
if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
printf("Error socket(): %s(%d)\n", strerror(errno), errno);
exit(1);
}
printf("socketfd is: %d\n", listenfd);
return listenfd;
}
int bindSocketToServer(int listenfd, int port)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listenfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
printf("Error bind(): %s(%d)\n", strerror(errno), errno);
return -1;
}
//It is normal here.
pirntf("It is still normal here.\n");
return 1;
}
pasvPort = 30000;
pasvFilefd = createSocket();
while(1)
{
printf("start.\n");
if(bindSocketToServer(pasvFilefd, pasvPort) > 0)
{
printf("going to break.\n");
break;
}
else
pasvPort += 1;
printf("error.\n");
}
printf("Listening port%d", pasvPort); //It can be printed.
These work fine when I start my server and listen to port 21 in main process. But when I try to handle 'pasv' command and bind a socket to a new port as follows(in another process created by fork()), the process dies and I don't know why.
Edit: That's how I use fork().And in serveOneClient() I handle the 'pasv' command.
pid = fork();
if(pid < 0)
{
printf("Error fork(): %s(%d)\n", strerror(errno), errno);
continue;
}
else if(pid == 0)
{
close(listenfd);
serveOneClient(connfd);
printf("serving one over.\n");
close(connfd);
return 0;
}
else
close(connfd);

Related

pthread_join fails in forking TCP server when handling multiple clients

I have to create a multithread TCP/IP server which contains a variable to count the number of clients connected (and those which disconnect) and print the number of clients connected when a client connects to the server.
This is my client.c file:
#define PORT 4444
int main ()
{
int clientSocket;
struct sockaddr_in serverAddress;
char buffer[1024];
ssize_t nread;
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
perror("[-]Errore durante la creazione della socket\n");
exit(-1);
}
printf("[+]Client socket has been created\n");
memset(&serverAddress, '\0', sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
perror("Errore con la connessione\n");
exit(-1);
}
while (1) {
printf("> ");
fflush(stdin);
scanf("%s", buffer);
if (nread != -1)
buffer[nread] = '\0';*/
if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {
perror("Errore con l'invio");
exit(1);
}
if(strcmp(buffer, ":exit") == 0) {
close(clientSocket);
printf("[-]Disconnected from Server\n");
exit(0);
}
if ( (nread=recv(clientSocket, buffer, sizeof buffer - 1, 0)) <= 0) {
perror("[-]Error in receiving data from server\n");
}
else {
buffer[nread] = '\0';
printf("Server received: %s\n", buffer);
}
}
close(clientSocket);
return 0;
}
and this is my server.c file:
#define PORT 4444
#define MAX_CONNESSIONI 100
typedef struct myStruct {
int clientCollegati;
int clientCheSiSonoScollegati;
pthread_mutex_t mutex; // Creazione del mutex per sincronizzare la struttura
} myStruct;
myStruct *test;
myStruct *initStruct();
void *incrementa(void*);
int main ()
{
int serverSocket, bindStatus;
struct sockaddr_in serverAddress;
int clientSocket;
struct sockaddr_in newAddress;
char buffer[1024];
pid_t child;
socklen_t addrSize;
ssize_t nread;
pthread_t tid;
test = initStruct();
if (pthread_create(&tid, NULL, incrementa, NULL) != 0) {
perror("Errore nella creazione del thread t1\n");
exit(1);
}
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
perror("[-]Errore durante la creazione della socket\n");
exit(-1);
}
memset(&serverAddress, '\0', sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
bindStatus = bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
if (bindStatus == -1) {
perror("[-]Errore durante il binding\n");
exit(1);
}
printf("[+]Bind to port %d\n", PORT);
if (listen(serverSocket, MAX_CONNESSIONI) != -1) {
printf("Listening . . .\n\n");
}
else {
perror("[-]Error during listening\n");
exit(1);
}
while (1) {
clientSocket = accept(serverSocket, (struct sockaddr*)&newAddress, &addrSize);
if (clientSocket == -1) {
exit(-1);
}
printf("%s:%d joined\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port));
if (pthread_join(tid, NULL)) { // returns 3
perror("pthread_join error\n");
exit(1);
}
printf("There is/are %d client(s) connected\n", test->clientCollegati);
child = fork();
if (child == 0) {
close(serverSocket);
while (1) {
if ( (nread=recv(clientSocket, buffer, sizeof buffer - 1, 0)) <= 0) {
perror("[-]Error in receiving data from server\n");
}
else {
buffer[nread] = '\0';
}
if (strcmp(buffer, ":exit") == 0) {
printf("%s:%d left\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port));
break;
}
else {
printf("%s:%d wrote: %s\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port), buffer);
send(clientSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(clientSocket);
return 0;
}
myStruct *initStruct()
{
struct myStruct *ptr = malloc(sizeof(myStruct));
ptr->clientCollegati = 0;
ptr->clientCheSiSonoScollegati = 0;
pthread_mutex_init(&ptr->mutex, NULL); // inizializzazione dinamica del mutex
return ptr;
}
void *incrementa(void *ptr)
{
pthread_mutex_lock(&test->mutex);
test->clientCollegati++;
pthread_mutex_unlock(&test->mutex);
pthread_exit(0);
}
Unfortunately this seems not to work properly, ans you can see server output and here client1 and here client2 output
Where's the mistake? I suppose that the problem is when tid finish and a second call to that pthread_join is invoked to a non-existent thread (because there is a single thread)
Your code logic is wrong. You are doing a single pthread_create() and then multiple pthread_join(). If you want to increment the values for every connected client you have to do one pthread_create() after every single successful accept(), followed by one pthread_join(). Note: all this must happen before the call to fork().
Where's the mistake? I suppose that the problem is when tid finish and a second call to that pthread_join is invoked to a non-existent thread (because there is a single thread)
That's exactly what happens. In your current program, the first pthread_join() is successful, and any successive call fails with errno 3 (no such process) because the thread doesn't exist anymore. So you already figured this out. Why are you creating one thread but joining it multiple times if you know that's wrong?
The way your program is written (fork after the increment) also means that there really is no reason at all to use threads to do the increment, and you don't even need the mutex, since only one single thread will access the value at any given time. In other words, your server isn't multithreaded at all. If you only want to do this as an experiment that's ok, but it doesn't make much sense.
What you probably want to do (to have a multithreaded server) is to have one thread per client instead of forking each time, with the client code in the thread function (in that case having a mutex makes sense). Beware though that this does not scale well for large numbers of clients (in general, the classical fork() approach is better, in which case you really don't need any thread).

Thread to open socket

Hello i made this code to open a socket and make a thread to send data so the socket
int is_valid_fd(int fd)
{
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
int main(int Count, char *Strings[])
{
pfd.events = POLLIN;
pfd.revents = 0;
/*---Create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("Socket");
exit(errno);
}
/*---Initialize address/port structure---*/
bzero(&self, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
/*---Assign a port number to the socket---*/
if ( bind(sockfd, (struct sockaddr*)&self, sizeof(self)) != 0 )
{
perror("socket--bind");
exit(errno);
}
/*---Make it a "listening socket"---*/
if ( listen(sockfd, 20) != 0 )
{
perror("socket--listen");
exit(errno);
}
err = pthread_create(&(tid), NULL, &thread_accept, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
/*---Forever... ---*/
while(1){
if(0<poll(&pfd,1,100)){
if(pfd.revents & POLLIN){
run = read(pfd.fd, &t,1);
}
}
if(run){
if(is_valid_fd(clientfd))send(clientfd, "12 ",3,0);
/*---Close data connection---*/
}
printf("hejsa\n");
fflush(stdout);
sleep(1);
}
/*---Clean up (should never get here!)---*/
close(sockfd);
return 0;
}
void* thread_accept(){
while (1){
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
pfd.fd=clientfd;
printf("%s:%d, connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
run=1;
/*---Echo back anything sent---*/
send(clientfd, buffer, recv(clientfd, buffer, MAXBUF, 0), 0);
//close(clientfd);
}
}
My problem is then, that when i close the socket connection, the program shuts down instead of just closing the socket and keep printf("hejsa\n)
I don't see where you break the while loop?
you should also protect your shared data with mutex or something.
I have a short example that do something similar(but in different way) here

Subsequent Messages not Received

I'm working on a networking project. I can successfully send a single message from my client program over to my server program. However, when I send a second message, the server apparently isn't receiving it. I say this because the client program generates output to suggest that the message was sent, but the server shows no reaction at all.
I'm thinking that I am doing something wrong with either select() or FD_ISSET(). Can anyone see what I am doing wrong? Thanks.
int main(int argc, char *argv[]) {
int sockfd, newfd;
struct sockaddr_in clientAddr;
unsigned int recvLen;
socklen_t addr_size = sizeof clientAddr;
fd_set read_set;
struct timeval tv;
char buffer[BUFFSIZE];
// prepare the address struct for the first client
bzero(&clientAddr,sizeof(clientAddr)); //zero the struct
clientAddr.sin_family = AF_INET; //address family (ipv4)
clientAddr.sin_port = htons(SERVER_PORT); //sets port to network byte order
clientAddr.sin_addr.s_addr = INADDR_ANY;
// create a listening connection to listen for requests from clients
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stdout, "Cannot create socket for client 0.\n");
fprintf(stdout, "Terminating program\n\n");
exit(1);
}
if (bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
fprintf (stdout, "Binding failed for client 0\n\n");
perror("bind failed");
exit (1);
}
if (listen(sockfd, 10) < 0) {
fprintf (stdout, "Listen() failed\n");
perror("listen() failed");
exit (1);
}
// accept the connection
if ((newfd = accept(sockfd, (struct sockaddr *)&clientAddr, &addr_size)) < 0) {
fprintf(stdout, "Error accepting inbound data from client 0\n");
perror(" accept() failed");
exit(EXIT_FAILURE);
}
// initialize the fd set
FD_ZERO(&read_set);
FD_SET(newfd, &read_set); // adding our socket to the set
tv.tv_sec = 0;
tv.tv_usec = TIMEOUT * 1000;
while (1) {
if ( select(newfd+1, &read_set, NULL, NULL, &tv) == -1) {
perror("select failure");
fprintf(stdout, "errno: %d\n", errno);
exit(EXIT_FAILURE);
}
if (FD_ISSET(newfd, &read_set)) {
bzero(buffer, BUFFSIZE);
recv(newfd, &buffer, BUFFSIZE, 0);
fprintf(stdout, "Received message: %s\n", buffer);
}
}
return 0;
}
After each select you need call FD_ZERO(&read_set); FD_SET(newfd, &read_set); again.
So just move those functions into the loop, before select.

UDP server not receiving data

UDP server doesn't receive the data sent by UDP client program.I feel there is something wrong im doing in UDP Server program. Thanks.
send_client_message = malloc(message_size);
recv_client_message = malloc(message_size);
sockaddr_in_length = sizeof(struct sockaddr_in);
/* Create a datagram socket.*/
server_sock = socket(AF_INET,SOCK_DGRAM,0);
if (server_sock == return_error)
{
printf("Error in opening a datagram socket\n");
exit(0);
}
printf("Host sock = %d\n",server_sock);
/* Bind a local name to the socket.*/
server_sockaddr_in.sin_family = AF_INET;
server_sockaddr_in.sin_port = 4999;
server_sockaddr_in.sin_addr.s_addr = INADDR_ANY;
rc = bind(server_sock,(struct sockaddr *)&server_sockaddr_in,
sockaddr_in_length);
if (rc == return_error)
{
printf("Error in binding - \n");
(void)close(server_sock);
exit(0);
}
/* Get the server information, and print its data out.*/
rc = getsockname(server_sock,(struct sockaddr *)&server_sockaddr_in,
&sockaddr_in_length);
if (rc != return_error)
{
printf("Server Information\n");
printf("--------------------------------\n");
printf("Server sock - %d\n",server_sock);
printf("Server IP address - %x\n",
server_sockaddr_in.sin_addr.s_addr);
printf("Server port # - %d\n\n",
server_sockaddr_in.sin_port);
}
optval = message_size;
optlen = sizeof(optval);
rc = setsockopt(server_sock,SOL_SOCKET,SO_SNDBUF,(char *)&optval,
optlen);
if (rc == return_error)
{
//printf("Error in setsockopt - %d\n",sock_errno());
printf("Error in setsockopt - \n");
(void)close(server_sock);
exit(0);
}
printf(".... Ready for clients ....\n");
/* Loop forever */
for (;;)
{
/* Monitor incoming buffers. */
rc = recvfrom(server_sock,recv_client_message,message_size,0,
(struct sockaddr *)&client_sockaddr_in,
&sockaddr_in_length);
printf("Recieved packet from %s: %d\nData: %s\n\n", inet_ntoa(client_sockaddr_in.sin_addr), ntohs(client_sockaddr_in.sin_port), recv_client_message);
fflush(stdout);
if (rc == return_error)
{
printf("Error in receiving message \n");
break;
}
} /* end of for(;;) */
/* Return the socket back to the system and exit normally. */
rc = close(server_sock);
if (rc == return_error)
{
printf("Error in closing the socket \n");
exit(0);
}
printf("Datagram server terminated\n");
exit(0);
}
for(i = 0; i < NPACK; i += 1) {
printf("Sending packet %d\n", i);
sprintf(buf, "This is packet %d\n", i);
if(sendto(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, slen) == -1)
diep("sendto()");
}
close(s);
return 0;
}
server_sockaddr_in.sin_port = 4999;
You likely want to htons that 4999.

How to use thread in my tcpserver program to communicate between two client through server?

int main()
{
int sock, connected, bytes_recieved , true = 1;
char send_data [1024] , recv_data[1024];
pid_t pid;
struct sockaddr_in server_addr,client_addr;
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(5000);
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 5000\n");
fflush(stdout);
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)\n", inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
//fork this process into a child and parent
pid = fork();
//Check the return value given by fork(), if negative then error,
//if 0 then it is the child.
if ( pid == -1)
{
perror("fork()");
}
//loop until client closes
if (pid == 0)
{
/*Child Process*/
close(sock);
while(1)
{
printf("\n SEND (q or Q to quit) : \n");
gets(send_data);
if (strcmp(send_data , "q") == 0 || strcmp(send_data , "Q") == 0)
{
send(connected, send_data,strlen(send_data), 0);
close(connected);
break;
}
else
send(connected, send_data,strlen(send_data), 0);
bytes_recieved = recv(connected,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
if (strcmp(recv_data , "q") == 0 || strcmp(recv_data , "Q") == 0)
{
close(connected);
break;
}
else
printf("\n RECIEVED DATA = from(%s,%d)\ndata=%s\n" ,inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port), recv_data);
fflush(stdout);
}
}
}
close(sock);
return 0;}
i want to use the thread for client to client communication.
but how to create the thread and where i have to create the thread for multi client communication.
i have also use fork for accessing the multiple client.
i want to make the multiple client chat program in c using tcp/ip concept
thanks!!!
You can create the client thread when accept() returns, passing client information to the thread function. From your code, it looks like you've managed to do it (I haven't really compiled and checked, but it looks OK). So perhaps you could add more information about what's wrong with your code.

Resources