I am trying to write a simple chat application using TCP protocol in Linux, in which server receives strings from the client and it sends strings size to the client. When I run client, the server throws a "Bad file descriptor" error and exits. Nevertheless if I send input strings by client it receives correct sizes of strings, but as I said before server goes down.
Here is the code :
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define MAX_LINE 1024
int main(int argc, char const *argv[]) {
int listen_fd, connect_fd, logging, str_lenght;
struct sockaddr_in serv_addr, client;
char buffer_str[MAX_LINE], buffer[MAX_LINE];
pid_t pid;
socklen_t len;
logging = 1;
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(-1);
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(1024);
if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("bind");
exit(-1);
}
if (listen(listen_fd, 1024) < 0) {
perror("listen");
exit(-1);
}
for (;;) {
len = sizeof(client);
if ((connect_fd = accept(listen_fd, (struct sockaddr *)&client, &len)) < 0) {
perror("accept");
exit(-1);
}
if ((pid = fork()) < 0) {
perror("fork");
exit(-1);
}
if (pid == 0) {
close(listen_fd);
for (;;) {
bzero(buffer_str, MAX_LINE);
if (read(connect_fd, buffer_str, sizeof(buffer_str)) < 0) {
perror("read");
exit(-1);
}
if (strcmp(buffer_str, "exit") == 0) break;
str_lenght = (int)strlen(buffer_str) - 1;
bzero(buffer_str, MAX_LINE);
snprintf(buffer_str, sizeof(buffer_str), "%d\n", str_lenght);
if (write(connect_fd, buffer_str, sizeof(buffer_str)) < 0) {
perror("write");
exit(-1);
}
if (logging) {
inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer));
printf("Request from host %s, port %d\n", buffer, ntohs(client.sin_port));
}
}
close(connect_fd);
exit(0);
} else close(listen_fd);
}
exit(0);
}
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define MAX_LINE 1024
void clientEcho(int socket_fd) {
char recv_buffer[MAX_LINE], send_buffer[MAX_LINE];
for (;;) {
bzero(recv_buffer, MAX_LINE);
bzero(send_buffer, MAX_LINE);
printf("insert string: ");
if (fgets(send_buffer, sizeof(send_buffer), stdin) == NULL) {
perror("fgets");
return;
}
if (write(socket_fd, send_buffer, sizeof(send_buffer)) < 0) {
perror("write");
return;
}
if (strcmp(send_buffer, "exit") == 0) break;
if (read(socket_fd, recv_buffer, sizeof(recv_buffer)) < 0) {
perror("read");
return;
}
printf("string size: ");
if (fputs(recv_buffer, stdout) < 0) {
perror("fputs");
return;
}
}
}
int main(int argc, char const *argv[]) {
int socket_fd;
struct sockaddr_in serv_addr;
if (argc != 2) {
perror("usage: <IPaddress>");
exit(-1);
}
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(-1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(1024);
if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) {
perror("inet_pton");
exit(-1);
}
if (connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("connect");
exit(-1);
}
clientEcho(socket_fd);
close(socket_fd);
exit(0);
}
In addition to what the other answer says: you're never sending the "exit" string, but "exit\n" (i.e. followed by a newfile -- and 1019 zero bytes), and the strcmp(buffer_str, "exit") == 0 in the server will never be true.
BTW, this piece is code is broken:
bzero(buffer_str, MAX_LINE);
if (read(connect_fd, buffer_str, sizeof(buffer_str)) < 0) {
perror("read");
exit(-1);
}
if (strcmp(buffer_str, "exit") == 0) break;
str_lenght = (int)strlen(buffer_str) - 1;
If the read returns exactly sizeof(buffer_str) bytes, the buffer may not be zero-terminated, and you could not use strcmp on it. And I don't see the point of setting str_lenght (sic) to one less than the actual length of the string.
As per the comment. Your server code is essentially the following...
if (listen(listen_fd, 1024) < 0) {
perror("listen");
exit(-1);
}
for (;;) {
len = sizeof(client);
if ((connect_fd = accept(listen_fd, (struct sockaddr *)&client, &len)) < 0) {
perror("accept");
exit(-1);
}
if ((pid = fork()) < 0) {
perror("fork");
exit(-1);
}
if (pid == 0) {
...
exit(0);
} else {
close(listen_fd); /* #Here */
}
}
exit(0);
Ate the line marked #Here you close the listening file descriptor listen_fd meaning the next...
connect_fd = accept(listen_fd, (struct sockaddr *)&client, &len)
call in the for (;;) loop will fail due to listen_fd being invalid.
Your subsequent comments suggest that might not be the only issue but I'm pretty sure it's the one causing the bad file descriptor: error on accept() error message.
Thank you to every one. This code run:
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define MAX_LINE 1024
int main(int argc, char const *argv[]) {
int listen_fd, connect_fd, logging, str_lenght;
struct sockaddr_in serv_addr, client;
char buffer_str[MAX_LINE], buffer[MAX_LINE];
pid_t pid;
socklen_t len;
logging = 1;
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(-1);
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(1024);
if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("bind");
exit(-1);
}
if (listen(listen_fd, 1024) < 0) {
perror("listen");
exit(-1);
}
for (;;) {
len = sizeof(client);
if ((connect_fd = accept(listen_fd, (struct sockaddr *)&client, &len)) < 0) {
perror("accept");
exit(-1);
}
if ((pid = fork()) < 0) {
perror("fork");
exit(-1);
}
if (pid == 0) {
for (;;) {
bzero(buffer_str, MAX_LINE);
if (read(connect_fd, buffer_str, sizeof(buffer_str)) < 0) {
perror("read");
exit(-1);
}
if (strcmp(buffer_str, "exit\n") == 0) break;
str_lenght = (int)strlen(buffer_str) - 1;
bzero(buffer_str, MAX_LINE);
snprintf(buffer_str, sizeof(buffer_str), "%d\n", str_lenght);
if (write(connect_fd, buffer_str, sizeof(buffer_str)) < 0) {
perror("write");
exit(-1);
}
if (logging) {
inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer));
printf("Request from host %s, port %d\n", buffer, ntohs(client.sin_port));
}
}
close(connect_fd);
exit(0);
} else close(connect_fd);
}
exit(0);
}
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define MAX_LINE 1024
void clientEcho(int socket_fd) {
char recv_buffer[MAX_LINE], send_buffer[MAX_LINE];
for (;;) {
bzero(recv_buffer, MAX_LINE);
bzero(send_buffer, MAX_LINE);
printf("insert string: ");
if (fgets(send_buffer, sizeof(send_buffer), stdin) == NULL) {
perror("fgets");
return;
}
if (write(socket_fd, send_buffer, sizeof(send_buffer)) < 0) {
perror("write");
return;
}
if (strcmp(send_buffer, "exit\n") == 0) break;
if (read(socket_fd, recv_buffer, sizeof(recv_buffer)) < 0) {
perror("read");
return;
}
printf("string size: ");
if (fputs(recv_buffer, stdout) < 0) {
perror("fputs");
return;
}
}
}
int main(int argc, char const *argv[]) {
int socket_fd;
struct sockaddr_in serv_addr;
if (argc != 2) {
perror("usage: <IPaddress>");
exit(-1);
}
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(-1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(1024);
if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) {
perror("inet_pton");
exit(-1);
}
if (connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("connect");
exit(-1);
}
clientEcho(socket_fd);
close(socket_fd);
exit(0);
}
Related
I am using raw sockets for the first time, so excuse me if my question exhibits serious lack of knowledge in this field.
My goal is to make a client-server program using raw sockets where client can send a string to server and server can send a reply. My codes are as follows:
/* server.c */
#include "../cn.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char const *argv[]) {
int sfd = socket(AF_INET, SOCK_RAW, 253);
if (sfd < 0) {
perror("Could not create socket");
exit(0);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("Could not bind");
}
int nsfd = accept(sfd, NULL, NULL);
if (nsfd < 0) {
perror("Could not accept");
exit(0);
}
char buffer[20];
int sz;
while (1) {
if ((sz = read(nsfd, buffer, 20)) < 0) {
perror("Could not read");
} else {
buffer[sz] = '\0';
strcat(buffer, " form server");
if (write(nsfd, buffer, strlen(buffer)) < 0) {
perror("Could not send");
}
}
}
return 0;
}
Client code:
#include "../cn.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char const *argv[]) {
int sfd = socket(AF_INET, SOCK_RAW, 253);
if (sfd < 0) {
perror("Could not create socket");
exit(0);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("Could not connect");
exit(0);
}
char buffer[20];
int sz;
while (1) {
scanf("%[^\n]s", buffer);
while (getchar() != '\n')
;
if (write(sfd, buffer, strlen(buffer)) < 0) {
perror("Could not write");
} else
if ((sz = read(sfd,buffer, 20)) < 0) {
perror("Could not read");
} else {
buffer[sz] = '\0';
printf("Reading: %s\n", buffer);
}
}
return 0;
}
Whenever I am trying to run the programs , it is showing error at the very time of socket creation itself:
Could not create socket: Operation not permitted
My questions are:
What am I missing in this case? Why does is this operation not permitted?
Though it is a broad question but, how to use raw sockets with custom protocol ID?
Is there any good material available for use of raw sockets with custom protocol?
I am trying to do a command line, based on socket communication.My only problem is that after exexvp is executed (and the data are being printed on the client's side), the client close and i want to keep him alive.
This is my code:
client.c
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#define PORT_NUMBER 1754
#define HOST_NUMBER
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, port_number, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
//fprintf(stderr, "usage %s hostname port\n", argv[0]);
//first parameter is ip address
printf("usage %s hostname port\n", argv[0]);
exit(0);
}
port_number = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0 )
error("ERROR opening socket!Socket failed!");
printf("Trying to connect...\n");
server = gethostbyname(argv[1]); //ip address
if (server == NULL) {
error( "ERROR, no such host");
//fprintf(stderr, "ERROR, no such host\n"); exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; //AF_UNIX
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(port_number);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Connected!\n");
printf("%s_>\n",argv[1]);
while(1) {
printf("Please enter the message: "); //THE CLIENT MUST WRITE A COMMAND
fgets(buffer, 256, stdin); //apo stdin sto buffer
n = write(sockfd, buffer, strlen(buffer)); //apo buffer sto socket
if(n < 0 ) {
error("ERROR writing to socket");
}
bzero(buffer, 256);
if ( recv(sockfd, buffer, 256, 0) < 0) {
printf("Server closed connection\n");
}
printf("%s\n", buffer);
}
return 0;
}
sever.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>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
void parse(char *vector_args[20], char *buffer){
buffer[strcspn(buffer, "\n")] =0;
int i=0;
char * pch;
pch = strtok (buffer," ");
while (pch != NULL )
{
vector_args[i]=pch;
printf (" %s\n",pch);
pch = strtok (NULL, " ");
i++;
}
vector_args[i]=NULL;
int k=0;
for(k=0; k<=i; k++) {
printf("vector %d = %s \n",k,vector_args[k]);
}
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
char str[INET_ADDRSTRLEN];
char *vector_args[20];
int status;
char *fd[2];
if (argc < 2)
{
fprintf(stderr, "No port provided\n");
exit(1);
}
unlink("sockfd"); //remove any old socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
int l = listen(sockfd, 5);
if (l < 0)
{
error("listen failed!");
}
clilen = sizeof(cli_addr);
printf( "Server waiting for a connection...\n " );
while(1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
if (inet_ntop(AF_INET, &cli_addr.sin_addr, str, INET_ADDRSTRLEN) == NULL) {
fprintf(stderr, "Could not convert byte to address\n");
exit(1);
}
fprintf(stdout, "Connected!\nThe client address is :%s\n", str);
//fork new process
int pid = fork();
if (pid == -1 ) {
error("ERROR in new process creation");
close(newsockfd);
continue;
}else if( pid != 0){
//parent process
close(newsockfd);//h edw h prin to continue
printf( " I am parent process %d\n " ,getpid()); //BGALE
if (wait(&status)== -1) /* Wait for child*/
{
perror( " wait " );
}
check_child_exit(status);
continue;
}else if (pid == 0) {
//child process
close(sockfd);
bzero(buffer, 256);
while(1) {
n = read(newsockfd, buffer, 255); //apo socket ston buffer
if (n < 0 )
error("ERROR reading from socket");
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "I got your message", 18);
bzero(buffer, 256);
close(1); //close stdin
dup2( newsockfd, 1);
close(0); //close stdout
dup2( newsockfd, 0);
parse(vector_args,buffer);
execvp(vector_args[0] , vector_args );
perror( " execvp " );
exit(EXIT_FAILURE);
bzero(buffer, 256);
}
close(newsockfd);
break;
}
}
}
Do you have any ideas how could I change my code in order to work properly?
The loop
while (1) {
....
execvp(....);
}
is effectively executed once. The reason is that the successful execvp replaces the code with whatever vector_args requests, and the executed process just exits when done.
If I understand your goals correctly (one process per connection, executing external commands in the loop), you need one more fork, along the lines of
while (1) {
....
if ((pid = fork()) == 0) {
execvp(....);
} else if (pid > 0) {
waitpid(....);
} else {
handle_error();
}
}
If client send pwd, server may recv p w d or pw d or pwd and so on.
In my opinion, if client want to send pwd, client should send pwd\n, server will read command until \n. If server want to send 123, server should send 123\0, client will read until \0. I write a tiny example, you could learn from it. The server code will continue until client quit.
server.c
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void parse(char** argv, char* buffer) {
int i = 0;
argv[i] = strtok(buffer, " ");
while (argv[i] != NULL) argv[++i] = strtok(NULL, " ");
}
void handle_client(int con_socket) {
for (;;) {
char buf[1024];
ssize_t i = 0;
for (;;) {
ssize_t ret = read(con_socket, buf + i, 1);
if (ret == 0) return;
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
++i;
}
int pipe_fd[2];
pipe(pipe_fd);
if (fork() == 0) {
close(con_socket);
dup2(pipe_fd[1], 1);
close(pipe_fd[0]);
close(pipe_fd[1]);
char* argv[25];
parse(argv, buf);
execvp(argv[0], argv);
exit(EXIT_FAILURE);
} else {
close(pipe_fd[1]);
for (;;) {
ssize_t ret = read(pipe_fd[0], buf, sizeof(buf));
if (ret == 0) {
write(con_socket, "", 1);
break;
}
write(con_socket, buf, ret);
}
wait(NULL);
}
}
}
int main() {
const char* server_ip = "127.0.0.1";
uint16_t server_port = 6666;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
int listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int opt = 1;
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bind(listen_socket, (struct sockaddr*)(&server_addr),
(socklen_t)(sizeof server_addr));
listen(listen_socket, 5);
for (;;) {
int con_socket = accept(listen_socket, NULL, NULL);
if (fork() > 0) {
close(con_socket);
wait(NULL);
continue;
} else {
close(listen_socket);
handle_client(con_socket);
close(con_socket);
break;
}
}
return 0;
}
client.c
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
const char* server_ip = "127.0.0.1";
uint16_t server_port = 6666;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
for (;;) {
printf(">> ");
char buffer[256];
fgets(buffer, 256, stdin);
if (strlen(buffer) == 0) continue;
write(sockfd, buffer, strlen(buffer));
for (;;) {
ssize_t ret = recv(sockfd, buffer, 256, 0);
buffer[ret] = '\0';
printf("%s", buffer);
if (buffer[ret - 1] == '\0') break;
}
}
return 0;
}
I'm trying to create a server-client socket scenario, in which more than one clients communicate with a server through socket. Server reads the data and sends back some acknowledgement and parallel saves some data.
My server.c code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
void serve(int);
struct data {
int checked;
int all;
}Data;
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno;
struct sockaddr_in serv_addr, cli_addr;
int pid;
socklen_t clilen;
if (argc < 2) {
fprintf(stderr,"ERROR: NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
fprintf(stderr,"ERROR: CANNOT CREATE SOCKET!\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr,"ERROR: CANNOT BIND CONNECTION!\n");
exit(1);
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
fprintf(stderr,"ERROR: CANNOT ACCEPT NEW CONNECTION!\n");
exit(1);
}
pid = fork();
if (pid < 0) {
fprintf(stderr,"ERROR: CANNOT CREATE NEW PROCESS!\n");
exit(1);
}
if (pid == 0) {
close(sockfd);
serve(newsockfd);
exit(0);
}
else
close(newsockfd);
}
return 0;
}
void serve(int new) {
int n;
int buffer[256];
int sum = 0;
int m = 0;
int i = 0;
int size = 0;
bzero(buffer, 256);
n = read(new, buffer, 256);
if (n == NULL) {
fprintf(stderr, "ERROR: CANNOT READ FROM CLIENT!\n");
exit(1);
}
do {
size++;
i++;
}while (buffer[i] != 0);
for (i = 0; i < size; i++)
sum += buffer[i];
m = sum / size;
sum = 0;
if (m > 10) {
Data.checked++;
Data.all++;
n = write(new, "Sequence OK", 11);
if (n == NULL) {
fprintf(stderr, "ERROR: CANNOT WRITE TO CLIENT!\n");
exit(1);
}
} else {
Data.all++;
n = write(new, "Check failed", 12);
}
printf("Data so far:\n1)Number of sequences received: %d\n2)Number of sequences with average above 10: %d\n", Data.all, Data.checked);
}
And my client.c code is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <memory.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int buffer[256];
char buffer2[13];
char answer;
int i;
int size = 0;
if (argc < 3) {
fprintf(stderr,"ERROR: CANNOT USE %s PORT!\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
fprintf(stderr, "ERROR: CANNOT CREATE SOCKET!\n");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR: NO HOST FOUND!\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy(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) {
fprintf(stderr, "ERROR: CANNOT CONNECT TO SERVER!\n");
exit(1);
}
do {
bzero(buffer, 256);
printf("Give the numbers now and enter 0 to stop\n");
for (i = 0; i < 256; i++) {
scanf("%d", &buffer[i]);
if (buffer[i] == 0)
break;
}
do {
size++;
i++;
}while (buffer[i] != 0);
n = write(sockfd, buffer, size);
if (n < 0) {
fprintf(stderr, "ERROR: CANNOT WRITE TO SERVER!\n");
exit(1);
}
bzero(buffer2, 13);
n = read(sockfd, buffer2, 13);
if (n < 0) {
fprintf(stderr, "ERROR: CANNOT READ FROM CLIENT!\n");
exit(1);
}
printf("%s\n", buffer2);
printf("Do you want to enter another sequence?\ty (yes) || n (no)\n");
scanf(" %c", &answer);
system("clear");
}while (answer == 'y');
return 0;
}
So the problem is that the server works with different clients (multiple terminals), but will not work with the same client after the first time. I'm new to this whole server-client thing so I'm struggling a bit. Does anyone have an idea?
Thanks in advance.
Hello so I've been working on this for quite awhile now and cannot figure it out.
I'm trying to set up a connection to a client using a specific port number. For some reason the child process is exiting if my While loop is included in the code. When I take the while loop out everything executes as intended. Any guidance?
Here's my code
> #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(int argc, char *argv[]){
if (argc < 2) {
printf("Please enter a port");
} else {
printf("test2");
int socketfd;
pid_t pid, sid;
//Fork
pid = fork();
if (pid < 0) {
perror("Fork failed");
exit(1);
}
if (pid > 0) {
printf("exiting");
exit(0);
}
if (pid == 0) {
printf("Hi");
sid = setsid();
if (sid < 0){
printf("failure");
}
//Start the Daemon
printf("Test");
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if(socketfd < 0){
printf("socket error");
}
int portNumber = atoi(argv[1]); //Port number entered in by user.
struct sockaddr_in server;
struct sockaddr_in clientAddress;
bzero((char *) &server, sizeof(server)); // Clear buffer for server address
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portNumber);
server.sin_family = AF_INET;
socklen_t clientLength;
printf("Test3");
if (bind(socketfd, (struct sockaddr *) &server, sizeof(server)) == -1)
{
perror("bind call failed");
}
printf("Test5");
listen(socketfd, 5);
clientLength = sizeof(clientAddress);
printf("Test6");
while(1) {
int client_socketfd;
int x;
client_socketfd = accept(socketfd, (struct sockaddr *) &clientAddress, &clientLength);
if(client_socketfd == -1){
perror("ERROR: \n");
}
FILE * pFile;
char receivedFile[1000];
char rawData[1000];
bzero(receivedFile, 1000);
if (read(client_socketfd,receivedFile,1000) == -1){
perror("Read Failure");
}
printf("Received File %s",receivedFile);
pFile = fopen(receivedFile, "r");
if(pFile == NULL){
perror("Cannot open file");
}
if(fgets(rawData,1000,pFile) != NULL) {
int fileLength = strlen(rawData);
for(x = 0; x < fileLength; x++){
printf("%s\n",rawData[x]);
}
} else {
perror("Nothing in the file!\n");
}
}
}
}
return 0;
}
Here's what happens when I compile and run the above code:
Here's the test I did to source the issue to the while loop.
> #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(int argc, char *argv[]){
if (argc < 2) {
printf("Please enter a port");
} else {
printf("test2");
int socketfd;
pid_t pid, sid;
//Fork
pid = fork();
if (pid < 0) {
perror("Fork failed");
exit(1);
}
if (pid > 0) {
printf("exiting");
exit(0);
}
if (pid == 0) {
printf("Hi");
sid = setsid();
if (sid < 0){
printf("failure");
}
//Start the Daemon
printf("Test");
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if(socketfd < 0){
printf("socket error");
}
int portNumber = atoi(argv[1]); //Port number entered in by user.
struct sockaddr_in server;
struct sockaddr_in clientAddress;
bzero((char *) &server, sizeof(server)); // Clear buffer for server address
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portNumber);
server.sin_family = AF_INET;
socklen_t clientLength;
printf("Test3");
if (bind(socketfd, (struct sockaddr *) &server, sizeof(server)) == -1)
{
perror("bind call failed");
}
printf("Test5");
listen(socketfd, 5);
clientLength = sizeof(clientAddress);
printf("Test6");
}
}
return 0;
}
This code successfully enters the child and prints out all the "Tests"
I wrote an application for communicating between two clients (one will run the server.c application, and the other one client.c).
Everything goes very good at this point, both sides (client and server) can send and receive messages (there are two processes in both sides: one for listening and printing messages, and one for receiving and sending back messages).
There is what I got so far:
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include "aes.h"
#define BSIZE 320
uint8_t key[] = "qwertyuioplkjhg";
uint8_t iv[] = "123456789098765";
void error(const char *msg) {
perror(msg);
exit(0);
}
int main(int argc, char *argv[]) {
int sockfd, portno, n, pid;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[BSIZE];
char paddedData[BSIZE];
unsigned char crypted_data[BSIZE];
if (argc < 3) {
fprintf(stderr,"usage %s <hostname> <port>\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, 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_INET;
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) {
switch(pid = fork()) {
case -1:
error("ERROR fork");
case 0:
while(1) {
//printf("Please enter the message: ");
bzero(buffer, BSIZE);
//printf("Message: ");
fgets(buffer, BSIZE - 1, stdin);
strncpy(paddedData, buffer, BSIZE);
AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv);
n = write(sockfd, crypted_data, BSIZE - 1);
if(n < 0) {
error("ERROR writing to socket");
}
}
default:
while(1) {
//bzero(buffer,256);
n = read(sockfd, buffer, BSIZE - 1);
AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv);
if(n < 0) {
error("ERROR reading from socket");
}
printf("<<server>>: %s", paddedData);
}
}
close(sockfd);
return 0;
}
and server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "aes.h"
#define BSIZE 320
uint8_t key[] = "qwertyuioplkjhg";
uint8_t iv[] = "123456789098765";
int numberOfConnections = 0;
void communications_handler(int);
void error(const char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if(argc < 2) {
fprintf(stderr, "ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
error("ERROR opening socket");
}
bzero((char*)&serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
error("ERROR on binding");
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
while(1) {
/* [1] */
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
numberOfConnections++;
printf("\nThere are %d clients connected!\n\n", numberOfConnections);
if (newsockfd < 0) {
error("ERROR on accept");
}
pid = fork();
if (pid < 0) {
error("ERROR on fork");
}
if (pid == 0) {
close(sockfd);
communications_handler(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
}
close(sockfd);
return 0;
}
void communications_handler(int sock) {
int n, pid;
char buffer[BSIZE];
char paddedData[BSIZE];
unsigned char crypted_data[BSIZE];
switch(pid = fork()) {
case -1:
error("ERROR on fork");
case 0:
while(1) {
n = read(sock, buffer, BSIZE - 1);
AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv);
if(n < 0) {
error("ERROR reading from socket");
}
printf("<<client>>: %s", paddedData);
}
default:
while(1) {
bzero(buffer, BSIZE);
//printf("Message: ");
fgets(buffer, BSIZE - 1, stdin);
strncpy(paddedData, buffer, BSIZE);
AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv);
for(int i = 0; i < numberOfConnections; i++) {
n = write(sock, crypted_data, BSIZE - 1);
}
if(n < 0) {
error("ERROR writing to socket");
}
}
}
}
Now I want to extend this program, by letting the server to accept multiple connections (I actually did this, in server.c, at [1]).
But there is now one problem: How can I implement the communication between two (or more) clients (the server will only accept new connections, read data from all connected clients, and send data back to all clients).
Can this be done with processes?
Have a look at Beej's guide to non-blocking socket programming: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select