Won't receive full data from server to client (unix - C) - c

I got a Unix shell in a server which should send the output the the client and then be printed out. I have tried several different methods to get the full output but i only get 3-5 letters even though I use a while-loop in recv which should be able to receive everything.
The server prints out the whole output but the client doesn't receive the whole data.
Server code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#define SOCK_PATH "echo_socket"
#define ORDLANGD 30
#define die(e) do { fprintf(stderr, e); exit(EXIT_FAILURE); } while (0);
void byt(char *foo);
void lasIn(char *a1, char *argv[]);
static void pSigHandler(int signo){
switch (signo) {
case SIGTSTP:
printf("TSTP");
fflush(stdout);
break;
}
}
int main(void)
{
int s, s2, t, len, newsockfd;
struct sockaddr_un local, remote;
char str[100];
char *argv[7];
char foo[4096];
int link[2];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
struct sigaction psa;
psa.sa_handler = pSigHandler;
sigaction(SIGTSTP, &psa, NULL);
for(;;) {
int done, n;
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("ERROR on fork");
exit(1);
}
if (pid == 0)
{
/* This is the client process */
close(s);
done = 0;
do {
n = recv(s2, str, 100, 0);
if (n <= 0) {
if (n < 0) perror("recv");
done = 1;
}
lasIn(str, argv);
if ((strcmp(argv[0], "exit")) == 0){
exit(0);
}
else if ((strcmp(argv[0], "cd")) == 0){
if ((chdir(argv[1])) != 0){
printf("Gar inte att byta katalog\n");
}
}
pid_t pid;
if (pipe(link)==-1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if(pid == 0) {
dup2 (link[1], STDOUT_FILENO);
close(link[0]);
execvp(argv[0], argv);
sleep (1);
exit(0);
} else {
close(link[1]);
read(link[0], foo, sizeof(foo));
printf("\n\n%s\n\n", foo);
wait(NULL);
}
if (!done)
{
if (send(s2, foo, n, 0) < 0) {
perror("send");
done = 1;
}
}
} while (!done);
}
else
{
close(s2);
}
}
return 0;
}
void lasIn(char *a1, char *argv[]){
int i;
argv[0] = strtok(a1, " \n");
for(i = 1; i < 6; i = i++) {
argv[i] = strtok(NULL, " \n");
if (argv[i] == NULL)
break;
}
argv[6] = NULL;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#define SOCK_PATH "echo_socket"
int main(void)
{
int s, t, len;
struct sockaddr_un remote;
char str[100];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Trying to connect...\n");
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
if (send(s, str, strlen(str), 0) == -1) {
perror("send");
exit(1);
}
while(1)
{
memset(str ,0 , 100); //clear the variable
if(recv(s , str , 100 , 0) < 0)
{
break;
}
else
{
printf("%s" , str);
break;
}
}
}
close(s);
return 0;
}

Given that you are getting some, not all of your expected traffic, perhaps one potential problem is the two break; statments in your code section:
while(1)
{
memset(str ,0 , 100); //clear the variable
if(recv(s , str , 100 , 0) < 0)
{
break;//here
}
else
{
printf("%s" , str);
break;//and here
}
}
The first time in, it will either break out of the while loop in one or the other branches, regardless of whether there is more data.
You might consider two additional things:
1) using an alternate call structure. Something like:
while(recv(s , str , 100 , 0) > 0)
{
...
}
//do some error checking here
2) put a small (fraction of a second) delay between leaving a successful send(,,,); and calling recv(,,,).
EDIT example of using terminating character with sockets
numBytesReceived = recv(irdaCommSocket, recvBuf, readBufsize, 0);
while(strstr(recvBuf, "%") == NULL)//uniques terminating character (use anything, including `\n`)
{
if (numBytesReceived < 0) return WSAGetLastError();//windows specific, change error handling for linux
strncpy(bufptr, recvBuf, readBufsize);
*pNumBytes += numBytesReceived;
numBytesReceived = recv(irdaCommSocket, recvBuf, readBufsize, 0);
}

Related

How can I program a file transfer system using UDP so that files are transferred instead of messages?

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int pid;
int sock;
void interrupt(int sig) {
close(sock);
if (pid) {
kill(pid, sig);
printf("Exiting...\n");
}
exit(0);
}
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("Usage: %s portnumber\n", argv[0]);
return 1;
}
signal(SIGINT, &interrupt);
signal(SIGTERM, &interrupt);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in addr = {
AF_INET,
htons(atoi(argv[1])),
INADDR_ANY
};
int res = bind( sock,
(struct sockaddr*)&addr,
sizeof(addr));
if (res < 0) {
perror("Bind");
return -1;
}
int pid = fork();
if (pid) {
while(1) {
char buf[100];
int chars = 0;
char c;
int portnumber;
scanf("%d", &portnumber);
struct sockaddr_in target = {
AF_INET,
htons(portnumber),
inet_addr("127.0.01")
};
while(read(0, &c, 1) > 0) {
if(c == '\n') {
// TODO send buf
sendto(sock, buf, chars, 0,
(struct sockaddr*)&target,
sizeof(target));
chars = 0;
break;
} else {
if (chars < 100)
buf[chars++] = c;
else
printf("\n->Maximum character is reached, press enter to send\n");
}
}
}
} else {
struct sockaddr_in incoming;
int lenincoming = sizeof(incoming);
char buf[101];
int chars = 0;
while( (chars = recvfrom(sock, &buf, 100, 0,
(struct sockaddr*)&incoming,
&lenincoming)) >= 0)
{
write(1, buf, chars);
write(1, "\n", 1);
buf[chars] = 0;
if (strcmp(buf, "ok") != 0) {
sendto( sock, "ok", 2, 0,
(struct sockaddr*)&incoming,
lenincoming);
}
}
}
return 0;
}
I want to modify this program so that a file can be sent. It should ask a port number and filename and then send the file in 100 byte packages to the other side. Every package should have starting point of the data. When I get data, I should seek to the location that is specified at the start of the data. Save to fixed filename or if you want transfer filename first. You can assume that you are working on the same system.
I read about "lseek(fd, start, SEEK_SET)". I think it should help. But how to combine it all?

bad file descriptor: error on accept() (socket)

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);
}

Getting a webserver to run Bash commands locally and output back to web page

I'm building an interactive web page so that a user can type a Bash command into the HTML page, click run and the output will display on the same page.
As of now my server can run commands if they are put into the search bar, but it doesn't work for piping or flags, just basic commands.
I'm looking for help understanding why pexec.c below provides no output, only a blank page.
**wrc-server.c**
/*
** server.c -- a stream socket server demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <poll.h>
#define PORT "3838" // The port users will be connecting to
#define BACKLOG 10 // How many pending connections queue will hold
void sigchld_handler(int s)
{
(void)s; // Quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
// Get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
char *parse(char *command) {
char * newCommand = (char *) malloc(sizeof(char)*35);
newCommand = strtok(command, " ");
newCommand = strtok(NULL, "/ ");
return newCommand;
}
char * execution(char *command) {
//printf("yo:%s\n", command);
int piper[2];
size_t len = 0;
pipe(piper);
char* output = malloc(1000 * sizeof(char));
memset(output, '\0', 1000* sizeof(char));
pid_t pid = fork();
if(pid != 0) // Parent
{
wait(NULL);
close(piper[1]);
int n = sizeof(output);
// ----Rob Code
struct pollfd * poll_fd = malloc(sizeof(struct pollfd));
poll_fd->fd = piper[0];
poll_fd->events = POLLIN;
//wait(NULL);
//printf("done\n");
//printf("AAA %s", output);
if (poll(poll_fd, 1, 0) == 1) { // Pipe data check
read(piper[0], output, 1000);
}
//printf("the command is %s\n", output);
//read(&output, output, piper[0]);
//printf("%s\n", piper[0]);
//dup2(piper[1], 1);
//close(0)
}
else {
//dup2(piper[1], 1);
//printf("run: %s", command);
close(1);
dup(piper[1]);
//close(0);
execlp(command, command, NULL);
exit(1);
}
// dup2 execute and print it out in parent
// if (*(commands+1) != NULL) // Redirect stdout as long as were not at the last row
// {
// dup2(piper[1], 1);
// close(piper[0]);
// }
return output;
}
int main(void)
{
int sockfd, new_fd; // Listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // Connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// Loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
//printf("%s\n", servinfo.ai_canonname);
freeaddrinfo(servinfo); // All done with this structure
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("server: waiting for connections...\n");
int ptds[2];
char *commands = malloc(sizeof(char)*1212);
while(1) { // Main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
char *buf = malloc(1000*sizeof(char));
memset(buf, '\0', 1000* sizeof(char));
recv(new_fd, buf, 1000*sizeof(char), 0);
//printf("%s\n", parse(buf));
;
if (!fork()) { // This is the child process
close(sockfd); // Child doesn't need the listener
if (send(new_fd, execution(parse(buf)), 1000, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
**pexec.c**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
static char* args[512];
pid_t pid;
int command_pipe[2];
#define READ 0
#define WRITE 1
static int command(int input, int first, int last)
{
int pipettes[2];
pipe(pipettes);
pid = fork();
if (pid == 0) {
if (first == 1 && last == 0 && input == 0) {
// First command
dup2(pipettes[WRITE], STDOUT_FILENO);
} else if (first == 0 && last == 0 && input != 0) {
// Middle command
dup2(input, STDIN_FILENO);
dup2(pipettes[WRITE], STDOUT_FILENO);
} else {
// Last command
dup2(input, STDIN_FILENO);
}
if (execvp( args[0], args) == -1)
_exit(EXIT_FAILURE);
}
if (input != 0)
close(input);
close(pipettes[WRITE]);
if (last == 1)
close(pipettes[READ]);
return pipettes[READ];
}
static void cleanup(int n)
{
int i;
for (i = 0; i < n; ++i)
wait(NULL);
}
static int run(char* cmd, int input, int first, int last);
static char line[1024];
static int n = 0; /* Number of calls to 'command' */
int main(int argc, char *argv[])
{
while (1) {
// for(int i = 1; i < argc; i++) {
// strcat(line, argv[i]);
// strcat(line, " ");
// }
/* Read a command line */
//if (!fgets(line, 1024, stdin))
//return 0;
int InputLength = atoi(getenv("INPUT_LENGTH"));
fread(line, InputLength, 1, stdin);
int input = 0;
int first = 1;
char* cmd = line;
char* next = strchr(cmd, '#'); /* Find first '|' */
while (next != NULL) {
/* 'next' points to '|' */
*next = '\0';
input = run(cmd, input, first, 0);
cmd = next + 1;
next = strchr(cmd, '#'); /* Find next '|' */
first = 0;
}
input = run(cmd, input, first, 1);
cleanup(n);
n = 0;
}
return 0;
}
static void split(char* cmd);
static int run(char* cmd, int input, int first, int last)
{
split(cmd);
if (args[0] != NULL) {
if (strcmp(args[0], "exit") == 0)
exit(0);
n += 1;
return command(input, first, last);
}
return 0;
}
static char* skipwhite(char* s)
{
while (isspace(*s))
++s;
return s;
}
static void split(char* cmd)
{
cmd = skipwhite(cmd);
char* next = strchr(cmd, ' ');
int i = 0;
while (next != NULL) {
next[0] = '\0';
args[i] = cmd;
++i;
cmd = skipwhite(next + 1);
next = strchr(cmd, ' ');
}
if (cmd[0] != '\0') {
args[i] = cmd;
next = strchr(cmd, '\n');
next[0] = '\0';
++i;
}
args[i] = NULL;
}

C socket: recv jams the program if used twice

I'm trying to implement C code on a UNIX platform which sends all files data to the client, and uploading a file from the client to the server.
The first part is working but for the second part I've encountered an issue.
After some debugging I've found out that the server side jams the client when I'm using recv the second time in the code [I've marked it for your convenience].
I've tried to look up on guides or what I'm doing wrong but I couldn't find the issue for what causing the program to get stuck.
For de-bugging purposes I'm now trying to send an int from client to the server
server side
#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 <sys/stat.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#define PORT 0x0da2
#define IP_ADDR 0x7f000001
#define QUEUE_LEN 20
int main(void)
{
//char directory[1024];
//chdir("server");
//getcwd(directory, sizeof(directory));
//printf("%s",directory);
DIR* directory;
struct dirent* ent;
int fd;
char buffer[1000] = {0};
char convert[100] = {0};
size_t array_size = 0;
struct stat fileStat;
if ((directory = opendir ("server")) == NULL)
{
perror ("Cannot open .");
return 1;
}
while ((ent = readdir(directory)) != NULL)
{
if (!( !strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) )
{
fd = openat(dirfd(directory), ent->d_name, 0);
if (fd == -1)
{
perror ("Can't get stats.");
return 1;
}
if(fstat(fd, &fileStat)== -1)
{
perror ("Can't get stats.");
return 1;
}
strcat(buffer,ent->d_name);
sprintf(convert,"%lld", (long long) fileStat.st_size);
strcat(buffer, " ");
strcat(buffer,convert);
strcat(buffer,"\n");
}
}
int listenS = socket(AF_INET, SOCK_STREAM, 0);
if (listenS < 0)
{
perror("socket");
return 1;
}
struct sockaddr_in s = {0};
s.sin_family = AF_INET;
s.sin_port = htons(PORT);
s.sin_addr.s_addr = htonl(IP_ADDR);
if (bind(listenS, (struct sockaddr*)&s, sizeof(s)) < 0)
{
perror("bind");
return 1;
}
if (listen(listenS, QUEUE_LEN) < 0)
{
perror("listen");
return 1;
}
struct sockaddr_in clientIn;
int clientInSize = sizeof clientIn;
while (1)
{
int newfd = accept(listenS, (struct sockaddr*)&clientIn, (socklen_t*)&clientInSize);
if (newfd < 0)
{
perror("accept");
return 1;
}
if (send(newfd, &buffer, strlen(buffer), 0) < 0)
{
perror("send");
return 1;
}
char namebuff[100] = {0};
char sizebuff[256] = {0};
//int size;
ssize_t nrecv;
int error = 0;
int fsize;
//int dataleft;
if ((nrecv = recv(newfd, &namebuff, sizeof(namebuff), 0)) < 0)
{
perror("recv");
return 1;
}
if((strstr(buffer,namebuff) != NULL))
{
error = -1;
if (send(newfd, &error, sizeof(int), 0) < 0)
{
perror("send");
return 1;
}
}
/*if ((nrecv = recv(newfd, &fsize, sizeof(int), 0)) < 0) //this line is what jams the program
{
perror("recv");
return 1;
}*/
if(error != -1) //
{
if ((nrecv = recv(newfd, &sizebuff, sizeof(sizebuff), 0)) < 0)
{
perror("recv");
return 1;
}
fsize = atoi(sizebuff);
}
printf("%s\n",namebuff);
printf("%d\n",fsize);
close(newfd);
}
close(listenS);
return 0;
}
client side
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <fcntl.h>
#define PORT 0x0da2
#define IP_ADDR 0x7f000001
int ctoi(char c) {
return c-'0';
}
int main(void)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
ssize_t nrecv;
struct sockaddr_in s = {0};
s.sin_family = AF_INET;
s.sin_port = htons(PORT);
s.sin_addr.s_addr = htonl(IP_ADDR);
if (connect(sock, (struct sockaddr*)&s, sizeof(s)) < 0)
{
perror("connect");
return 1;
}
printf("Successfully connected.\n");
char buffer[1000] = {0};
if ((nrecv = recv(sock, &buffer, sizeof(buffer), 0)) < 0)
{
perror("recv");
return 1;
}
printf("./client list-files\n%s\n", buffer); //nrcev gives the size of the data is recived
int fd;
//int i;
//ssize_t nwrite, nread;
char sizebuff[256];
struct stat file_stat;
int numcheck = 0;
//char buffer2[4096];
char namebuff[100] = "coolfile.txt";
fd=open("coolfile.txt",O_RDONLY);
if (send(sock, &namebuff, strlen(namebuff), 0) < 0)
{
perror("send");
return 1;
}
/*if ((nrecv = recv(sock, &numcheck, sizeof(int), 0)) < 0)
{
perror("recv");
return 1;
}*/
if (numcheck == -1)
{
printf("file already exists in the server\n");
return 1;
}
if (fstat(fd, &file_stat) < 0)
{
printf("error");
return 1;
}
sprintf(sizebuff, "%ld", file_stat.st_size);
//printf("%s\n",sizebuff);
/*int number = 5;
if(send(sock, &number, sizeof(int), 0) < 0)
{
printf("error");
return 1;
}*/
if(send(sock, &sizebuff, strlen(sizebuff), 0) < 0);
{
printf("error");
return 1;
}
/*
nread = read(fd, buffer2, 4096);
for (i = 0; i < nread; i += nwrite)
{
nwrite = write(sock, buffer2 + i, nread - i);
}
} while (nread != 0);*/
return 0;
}
Thanks for your help!

C - simple encrypting socket with tcp connections fail to encrypt big files

Its using a blocking queue for encrypting files with XOR.
The buffers are set to be very big, but still when i encrypt the encryption of big files (1000 chars and more) I should receive the same file, but I am receiving only the beginning. Anyone knows how to fix this?
thanks.
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/select.h>
#include <netinet/tcp.h>
#include "os_queue.c"
#define BACKLOGGED_CONNECTIONS 10
queue_t new_queue;
int i=0;
void *worker_thread(void* key_path) {
int j = i;
i++;
printf("worker %d stssssart\n",j);
int rc;
int sockfd;
int key_fd;
if ((key_fd = open(key_path, O_RDONLY)) < 0) {
printf("ERROR: open key file failed: %s\n",strerror(errno));
exit(1);
}
while (1) {
rc = queue_dequeue(&new_queue,&sockfd);
if (rc != 0) {
printf("error! dequeue of a client's sockfd from the shared queue failed: %d\n",rc);
}
if(cipher(sockfd,key_fd)!=0){
printf("chipher did not work");
exit(1);
}
}
printf("worker %d finish\n",j);
close(key_fd);
pthread_exit((void*) &key_fd);
}
int cipher(int sockfd,int key_fd){
int keyFileFD, numberOfBytes,loop,n,key_num,totalsent,nsent,i;
char inputBuffer[262144], keyBuffer[262144],outputBuffer[262144];
if(lseek(key_fd,0,SEEK_SET) == -1){
printf("lseek function failed %s\n", strerror(errno));
return errno;
}
while (1) {
n = read(sockfd, inputBuffer, sizeof(inputBuffer));
if(n < 0){
if(errno ==EPIPE || errno == ENOTCONN || errno == ECONNRESET) {
printf("111");
close(sockfd);
return 0;
}
else{
printf("Read error: %s\n", strerror(errno));
close(sockfd);
return 0;
}
}
key_num=read(key_fd, keyBuffer, n);
if (key_num < 0) {
printf("Error reading file: %s\n", strerror(errno));
return errno;
}
while (key_num<n) {
if(lseek(key_fd,0,SEEK_SET) == -1) {
/*
*error
*/
printf("lseek function failed %s\n", strerror(errno));
return errno;
}
int cont=read(key_fd, keyBuffer+key_num, n-key_num);
if (cont == -1) {
printf("Error reading file: %s\n", strerror(errno));
return errno;
}
key_num=key_num+cont;
}
for(i=0;i<n;i++){
outputBuffer[i] = (inputBuffer[i] ^ keyBuffer[i]);
}
if(write(sockfd, outputBuffer,n)<0) {
if(errno ==EPIPE || errno == ENOTCONN || errno == ECONNRESET) {
close(sockfd);
return 0;
} else{
printf("Read error: %s\n", strerror(errno));
close(sockfd);
return 0;
}
}
close(sockfd);
}
return 0;
}
int main(int argc, char *argv[]) {
int base_sockfd, new_sockfd,i, rc, keyFileFD, num_of_workers,addrsize_1,addrsize_2;
struct sockaddr_in serv_addr, client_addr;
char* key_path = argv[3];
addrsize_1 = sizeof(struct sockaddr);
num_of_workers = atoi(argv[1]);
if(argc!=4){
printf("number of args is not 4: %s\n",strerror(errno));
return errno;
}
if(access(key_path, R_OK)<0){
printf("Key file does not exist or the file is not accessible: %s\n",strerror(errno));
return errno;
}
/*init data structures*/
rc = init_queue(&new_queue,2*num_of_workers);
if (rc!=0) {
printf("error! shared queue init failed\n");
return 1;
}
pthread_t threads[num_of_workers];
/*create workers*/
for (i = 0; i < num_of_workers; i++) {
rc = pthread_create(&threads[i], NULL, worker_thread, (void*) key_path);
if (rc != 0) {
printf("error! pthread_create() failed: %d\n", rc);
return 1;
}
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[2])); // short, network byte order
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//INADDR_ANY;
if ((base_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
printf("error! socket() failed: %s\n", strerror(errno));
return errno;
}
if (bind(base_sockfd, (struct sockaddr *)&serv_addr, addrsize_1) < 0) {
printf("error! bind() failed: %s\n", strerror(errno));
close(base_sockfd);
return errno;
}
addrsize_2 = sizeof(struct sockaddr_in);
if (listen(base_sockfd,SOMAXCONN) < 0) {
printf("error! listen() failed: %s\n", strerror(errno));
return errno;
}
while(1){
if ( (new_sockfd = accept(base_sockfd, (struct sockaddr*)&client_addr, &addrsize_2)) <= 0) {
printf("error! accept() failed: %s\n", strerror(errno));
close(base_sockfd);
return errno;
}
/*we have a new valid client sockfd, so enqueue it*/
rc = queue_enqueue(&new_queue, new_sockfd);
if (rc!= 0) {
printf("error! enqueue to shared queue failed withe value:%d\n",rc);
return 1;
}
}
/*clean up and close resources*/
rc=free_queue(&new_queue);
if(rc!=0)
printf("error! free queue failed with value:%d\n",rc);
return 1;
//close(base_sockfd);
/*exit gracefully*/
}
queue:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
typedef struct queue {
int *arr;
int capacity;
int size;
int in;
int out;
pthread_mutex_t mutex;
pthread_cond_t cond_full;
pthread_cond_t cond_empty;
} queue_t;
int queue_enqueue(queue_t *queue, int value) {
int rc;
rc = pthread_mutex_lock(&(queue->mutex));
if(rc!=0){
return rc;
}
while (queue->size == queue->capacity) {
pthread_cond_wait(&(queue->cond_full), &(queue->mutex));
}
queue->arr[queue->in] = value;
++ queue->size;
++ queue->in;
queue->in %= queue->capacity;
rc = pthread_mutex_unlock(&(queue->mutex));
if(rc!=0){
return rc;
}
rc = pthread_cond_signal(&(queue->cond_empty));
if(rc!=0){
return rc;
}
}
int queue_dequeue(queue_t *queue,int *value){
int rc;
rc = pthread_mutex_lock(&(queue->mutex));
if(rc!=0){
return rc;
}
while (queue->size == 0){
pthread_cond_wait(&(queue->cond_empty), &(queue->mutex));
}
*value = queue->arr[queue->out];
-- queue->size;
++ queue->out;
queue->out %= queue->capacity;
rc = pthread_mutex_unlock(&(queue->mutex));
if(rc!=0){
return rc;
}
rc = pthread_cond_signal(&(queue->cond_full));
return rc;
}
int init_queue(queue_t *new_queue,int cnt) {
int rc;
new_queue->capacity = cnt;
new_queue->arr = malloc(sizeof(cnt)*sizeof(int));
if (new_queue->arr== NULL) {
return -1;
}
new_queue->size = 0;
new_queue->in = 0;
new_queue->out = 0;
//init shared queue lock (mutex)
rc = pthread_mutex_init(&(new_queue->mutex), NULL);
if (rc != 0) {
return rc;
}
//init shared queue conditions variable
rc = pthread_cond_init(&(new_queue->cond_full), NULL);
if (rc != 0) {
return rc;
}
rc = pthread_cond_init(&(new_queue->cond_empty), NULL);
if (rc != 0) {
return rc;
}
}
int free_queue(queue_t *queue_to_kill) {
int rc;
rc = pthread_mutex_destroy(&(queue_to_kill->mutex));
if (rc) {
return rc;
}
rc = pthread_cond_destroy(&(queue_to_kill->cond_empty));
if (rc) {
return rc;
}
rc = pthread_cond_destroy(&(queue_to_kill->cond_full));
if (rc) {
return rc;
}
}
client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
int connectToHostname(int sock, char* hostname, char* port);
int main(int argc, char* argv[]){
int sock;
char* hostname;
char* port;
/* place default port if required*/
if(argc < 3)
{
port = "42666";
}
else
{
port = argv[2];
}
/* place default hostname if required*/
if(argc == 1)
{
hostname = "localhost";
}
else
{
hostname = argv[1];
}
/* open TCP socket with IPv4*/
if((sock = socket(PF_INET, SOCK_STREAM, 0))<0)
{
perror("Could not open socket");
exit(errno);
}
int fd = -1;
int fd2 = -1;
if(argc >= 4)
{
fd = open(argv[3], O_WRONLY|O_CREAT|O_TRUNC, 0666);
}
if(argc >= 5)
{
fd2 = open(argv[4], O_RDONLY, 0);
}
connectToHostname(sock, hostname, port);
char buf[100];
while(1)
{
if(fd2 <0)
{
scanf("%99s",buf);
send(sock, buf, strlen(buf), 0);
}
else
{
int stupid = read(fd2, buf, 99);
if(stupid == 0)
{
close(sock);
exit(0);
}
send(sock, buf, stupid, 0);
}
int sz = recv(sock, buf, 99, 0);
buf[100] = '\0';
if(fd< 0)
{
printf("%s\n", buf);
}
else
{
write(fd, buf, sz);
}
}
}
int connectToHostname(int sock, char* hostname, char* port)
{
int rv;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_in *h;
struct sockaddr_in dest_addr;
/* server addr is IPv4*/
dest_addr.sin_family = AF_INET;
/* write server port*/
dest_addr.sin_port = htons((short)strtol(port, NULL,10));
/* zero out hints (since garbage is bad)*/
memset(&hints, 0, sizeof(hints));
/* we want IPv4 address and TCP*/
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
/* try get address info*/
if((rv = getaddrinfo(hostname, port, &hints, &servinfo)) != 0)
{
fprintf(stderr, "Error getting address info: %s\n", gai_strerror(rv));
exit(1);
}
p = servinfo;
while(p!= NULL)
{
/* put last address into sent pointer*/
h = (struct sockaddr_in *)p->ai_addr;
dest_addr.sin_addr = h->sin_addr;
if(connect(sock, (struct sockaddr*)(&dest_addr), sizeof(struct sockaddr)) == 0)
break;/* if connection succesfull*/
p = p->ai_next;
}
freeaddrinfo(servinfo);
if(p == NULL)
{
/*We didnt find a host*/
perror("Could not connect to server");
exit(errno);
}
return 0;
}
i used this script to test it:
echo niv > key_file
echo is > read_file_b
echo thethethethethethethethethethe > read_file_c
echo se > read_file_d
echo rse > read_file_e
echo rse > read_file_f
echo aaaaaaa > write_file_a
echo bbbbbbb > write_file_b
echo ccccccc > write_file_c
echo ddddddd > write_file_d
echo ddddddd > write_file_e
echo ddddddd > write_file_f
gcc setos_server.c -pthread -o setos_server
./setos_server 3 2 key_file &
sleep 0.1
#printf "\n\n"
gcc client.c -pthread -o client
./client 127.0.0.1 2 write_file_a read_file_a &
./client 127.0.0.1 2 write_file_b read_file_b &
./client 127.0.0.1 2 write_file_c read_file_c &
./client 127.0.0.1 2 write_file_d read_file_d &
./client 127.0.0.1 2 write_file_e read_file_e &
./client 127.0.0.1 2 write_file_f read_file_f &
./client 127.0.0.1 2 final_file_a write_file_a &
./client 127.0.0.1 2 final_file_b write_file_b &
./client 127.0.0.1 2 final_file_c write_file_c &
./client 127.0.0.1 2 final_file_d write_file_d &
./client 127.0.0.1 2 final_file_e write_file_e &
./client 127.0.0.1 2 final_file_f write_file_f &
sleep 2
pkill setos_server
when read_file_a is a big file (more then 10000 chars).
thank you for your help.
One too many close()
while (1) {
n = read(sockfd, inputBuffer, sizeof(inputBuffer));
if(n < 0){
....
}
close(sockfd);
}
kills the socket after the very first read().
PS: shorter functions and correct formatting makes it very easy to spot.

Resources