Sending a normal .txt file works perfectly fine. But if I try to send a .wav file, the output file that gets generated is only a fraction of the size of the input file (and it doesn't play anything). I've tried pretty much everything I could find on Google, it might have something to do with not reading the .wav file correctly. But I'm reading and writing one character at a time, so I don't know why that should be a problem. Also, doing this over localhost. Any help would be greatly appreciated, thank you!
server.c
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define BUFFER_SIZE 32
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, n;
socklen_t clilen, servlen;
char buffer[BUFFER_SIZE];
FILE *fp;
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);
servlen = sizeof(serv_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer, BUFFER_SIZE);
n = read(newsockfd, buffer, BUFFER_SIZE);
if (n < 0) error("ERROR reading from socket");
printf("Received file name: %s\n", buffer);
fp = fopen(buffer, "rb");
if (fp == NULL)
printf("File open failed!\n");
else
printf("File successfully opened!\n");
while (1) {
bzero(buffer, BUFFER_SIZE);
char ch;
int i;
for (i = 0; i < BUFFER_SIZE; i++) {
ch = fgetc(fp);
buffer[i] = ch;
if (ch == EOF)
break;
}
n = write(newsockfd, buffer, BUFFER_SIZE);
if (n < 0)
error("ERROR writing to socket");
if (ch == EOF)
break;
}
printf("File sending complete...\n");
if (fp != NULL)
fclose(fp);
close(newsockfd);
close(sockfd);
return 0;
}
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>
#define BUFFER_SIZE 32
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[BUFFER_SIZE];
FILE *out;
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");
printf("Enter the file name: ");
bzero(buffer, BUFFER_SIZE);
fgets(buffer, BUFFER_SIZE - 1, stdin);
buffer[strlen(buffer) - 1] = '\0';
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
out = fopen("out.wav", "wb");
while (1) {
bzero(buffer, BUFFER_SIZE);
int i, j;
n = read(sockfd, buffer, BUFFER_SIZE);
if (n < 0)
error("ERROR reading from socket");
char ch;
for (i = 0; i < BUFFER_SIZE; i++) {
ch = buffer[i];
if (ch == EOF)
break;
j = (int)ch;
fputc(j, out);
}
if (ch == EOF)
break;
}
printf("File write complete... You can now use the output file!!\n");
if (out != NULL)
fclose(out);
close(sockfd);
return 0;
}
To determine the end-of-transmission, you have to check the return value of read(), rather than checking for EOF in the read data.
I have also taken the liberty to restructure and simplify your code.
Consider the following (untested) changes:
server.c:
// ...
while (1) {
size_t num_read = fread(buffer, 1, BUFFER_SIZE, fp);
if (num_read == 0) // end of file.
break;
n = write(newsockfd, buffer, num_read);
if (n < 0) // Error
error("ERROR writing to socket");
else if (n == 0) // Could handle this too
break;
}
// ...
client.c:
// ...
while (1) {
n = read(sockfd, buffer, BUFFER_SIZE);
if (n < 0)
error("ERROR reading from socket");
else if (n == 0) // Socket closed. Transfer is complete (or borked)
break;
fwrite(buffer, 1, n, out); // Could check fwrite too.
}
// ...
Related
I currently trying to create a program that you can connect from anywhere via the internet using sockets. I obviously want to execute commands and display the output to the client but also want to return anything that the client typed and if it was received, display message reveived. My problem is that even though it displays what was send, it doesn't execute commands. I have tryied to use gdb with break lines inide the while loop but they don't work as if the while loop is never executed.
Server:
#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 <sys/wait.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
char buffer[256];
char* comm[20],*cbuff;
struct sockaddr_in serv_addr, cli_addr;
int n,i;
char str[INET_ADDRSTRLEN];
char* args;
if (argc < 2)
{
fprintf(stderr, "No port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
memset((char *) &serv_addr, 0, 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");
for(;;){
listen(sockfd, 5);
clilen = sizeof(cli_addr);
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, "The client address is :%s\n", str);
while(1){
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0) error("ERROR reading from socket");
if(buffer=="exit"){
printf("Exiting...\n");
break;
}
cbuff=strtok(buffer," ");
i=0;
while(cbuff!=NULL){
cbuff=strtok(NULL," ");
comm[i]=cbuff;
i++;
}
if ((pid=fork())==-1){
perror("fork");
}
if(pid!=0){
wait(NULL);
}
else{
dup2(newsockfd,1);
printf("executing...\n");
execvp(comm[0],comm);
perror("execvp");
exit(EXIT_FAILURE);
}
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "message received", 17);
if (n < 0) error("ERROR writing to socket");
}
break;
}
close(newsockfd);
close(sockfd);
return 0;
}
Client:
#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>
void error(const char *msg){
perror(msg);
exit(0);
}
int main(int argc, char *argv[]){
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
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");
do{
printf("Please enter the message: ");
bzero(buffer, 256);
fgets(buffer, 255, stdin);
if(buffer=="exit"){
printf("Exiting...\n");
break;
}
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer, 256);
n = read(sockfd, buffer, 255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n", buffer);
}while(1);
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.
I don't know why it gets into a infinite loop and does not download the file when I try to execute that command line:
./server 2000
./client get filename localhost 2000 256
I have two doubts. First one is why the list of files comes with some dots on it. Second one is why I can't download the file from the server directory.
client code
#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 <errno.h>
#include <arpa/inet.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int file_size;
FILE *received_file;
int remain_data = 0;
ssize_t len;
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
int TamBuffer;
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
if(strcmp(argv[1],"list")==0){
TamBuffer=atoi(argv[4]);
char *comando = argv[1];
portno = atoi(argv[3]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[2]);
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");
n=write(sockfd,comando,strlen(comando));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,TamBuffer);
bzero(buffer,TamBuffer);
n = read(sockfd,buffer,TamBuffer-1);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
}
if (strcmp(argv[1],"get")==0){
TamBuffer=atoi(argv[5]);
char *comando = argv[1];
portno = atoi(argv[4]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[3]);
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");
strcat(comando,argv[2]);
n=write(sockfd,comando,strlen(comando));
if (n < 0)
error("ERROR writing to socket");
/* Receiving file size */
recv(sockfd, buffer, TamBuffer, 0);
file_size = atoi(buffer);
fprintf(stdout, "\nFile size : %d\n", file_size);
received_file = fopen("newfile", "w");
if (received_file == NULL)
{
fprintf(stderr, "Failed to open file foo --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
remain_data = file_size;
while (((len = recv(sockfd, buffer, TamBuffer, 0)) > 0) && (remain_data > 0))
{
fwrite(buffer, sizeof(char), len, received_file);
remain_data -= len;
int received_byte = len;
fprintf(stdout, "Receive %d bytes and we hope :- %d bytes\n", received_byte, remain_data);
}
fclose(received_file);
close(sockfd);
}
return 0;
}
server code
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
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;
int sent_bytes = 0; // bytes de envio de arquivo
char file_size[256]; //tamanho do arquivo
struct stat file_stat;
off_t offset;
int remain_data;
ssize_t len;
int fd;
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);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
if(strcmp("list",buffer)==0){
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
n=write(newsockfd,dir->d_name,strlen(dir->d_name));
n=write(newsockfd, "\n",1);
if (n < 0) error("ERROR writing to socket\n");
}
closedir(d);
}
}
else {
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
int i;
for(i=0;i<strlen(buffer);i=i+1){
buffer[i]=buffer[3+i];
}
printf("%s\n",buffer);
char* FILE_TO_SEND = buffer;
fd = open(FILE_TO_SEND, O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, &file_stat) < 0)
{
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
int num_filesize = file_stat.st_size;
fprintf(stdout, "File Size: \n%d bytes\n", num_filesize);
/* Sending file size */
len = send(newsockfd, file_size, sizeof(file_size), 0);
if (len < 0)
{
fprintf(stderr, "Error on sending greetings --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
printf("teste1/n");
int num_bytes_sent= len;
fprintf(stdout, "Server sent %d bytes for the size\n", num_bytes_sent);
offset = 0;
remain_data = file_stat.st_size;
/* Sending file data */
printf("teste2/n");
while (((sent_bytes = sendfile(newsockfd, fd, &offset, 256)) > 0) && (remain_data > 0))
{
fprintf(stdout, "1. Server sent %d bytes from file's data, offset is now : %d and remaining data = %d\n", sent_bytes, offset, remain_data);
remain_data -= sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from file's data, offset is now : %d and remaining data = %d\n", sent_bytes, offset, remain_data);
}
}
close(newsockfd);
close(sockfd);
return 0;
}
Basically my program is suppose to be able to have multiple connections to a server at the same time. Which I have running, except when they have to send large amounts of text via a socket, then it is unpredictable. Sometimes it works, sometimes not. The plaintext4 file is 69,333 bytes long, when I try to send it 5 times at the same time over the network via a socket to a server and back, it doesn't work always; sometimes it works, sometimes parts of it is missing, etc. When I used basically the same thing using write and read it worked, but when I tried to the same with large amounts of text, it didn't work almost at all, hence why I switched to send and recv. Now I can't figure out how to make it so when someone is sending sometime, no one else will send at the same time... because I think that is the problem I am having. Any help would great.
The status of my program right now:
- Works when sending small amounts of text.
- Doesn't work when sending large amounts of text.
- The size of the file that it creates when it doesn't work can vary, sometimes is above 60K bytes sometimes as little as 20K bytes. Meaning that probably one of the other processes wrote to the socket or read from it before the correct process got to receive it. (I think).
server 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>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
const int BUFF_SIZE = 70000;
int sockfd, newsockfd, portno, newsockfdc;
socklen_t clilen;
char buffer[BUFF_SIZE];
pid_t pid;
int status;
char temp[BUFF_SIZE];
struct sockaddr_in serv_addr, cli_addr;
int n;
int i;
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);
while(1){
waitpid(-1, &status, WNOHANG);
memset(buffer, '\0', sizeof(buffer));
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
if((pid=fork())==0)
{
close(sockfd);
int d;
for(i=0; i<1; i++)
{
bzero(buffer,BUFF_SIZE);
//sleep(1);
d=BUFF_SIZE-1;
//n = read(newsockfd,buffer,d);
n = recv(newsockfd, buffer, sizeof(buffer), 0);
if (n < 0) error("ERROR reading from socket");
bzero(temp, BUFF_SIZE);
strcpy(temp, buffer);
n = send(newsockfd, buffer, strlen(buffer)+1, 0);
//n = write(newsockfd,temp,sizeof(temp));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
exit(0);
}
else{
waitpid(-1, &status, WNOHANG);
close(newsockfd);
}
}
close(sockfd);
return 0;
}
client code
#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>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
const int BUFF_SIZE = 70000;
char buffer[BUFF_SIZE];
if (argc < 4) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
int numt;
numt = atoi(argv[3]);
char numc[5];
bzero(numc, 5);
sprintf(numc, "%d", numt);
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");
bzero(buffer,BUFF_SIZE);
FILE *fp;
size_t bytes_read;
if((fp=fopen("./plaintext4", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
sleep(1);
n=send(sockfd, buffer, strlen(buffer)+1, 0);
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
if (n < 0)
error("ERROR reading from socket");
char filei[90];
bzero(filei,90);
strcpy(filei, "plaintext");
strcat(filei, numc);
strcat(filei, "_a");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
//sleep(1);
printf("Sending message 1: plaintext1\n");
bzero(buffer,BUFF_SIZE);
if((fp=fopen("./plaintext1", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
n = send(sockfd, buffer, strlen(buffer)+1, 0);
//n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error ("ERROR writing to socket client side");
bzero(buffer, BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
//n = read(sockfd, buffer, n);
if (n < 0)
error("ERROR reading from socket client side");
printf("message: %s\n", buffer);
strcat(filei, "b");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
}
You server process can (which process accept() call) can be blocked by waitpid - it is can be cause of your problem.
Alternatively you can implement waitpid call via SIGCHLD signal handler and remove waitpid from main().
Best regards!
I'm trying to write a program in TCP where both client and server side are able to communicate until either one sends quit, which terminates the connection. Right now, the client side is able to send stuff, but when the server side sends something, there is a seg fault on the client side. Apologies in advance if my code in not up to par as I am fairly new to coding. Any help would be greatly appreciated
here is my code:
//Client side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5432
#define MAX_LINE 256
int main(int argc, char * argv[])
{
struct hostent *hp;
struct sockaddr_in serv_addr;
char *host;
char buf[MAX_LINE];
int n, size;
int sockfd;
if (argc == 2) {
host = argv[1];
}
else {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "error: can't find such host: %s\n", host);
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)hp->h_addr,(char *)&serv_addr.sin_addr.s_addr,hp->h_length);
serv_addr.sin_port = htons(SERVER_PORT);
size = sizeof(serv_addr);
//active open
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd <0) {
error("ERROR opening socket");
exit(1);
}
printf("successfully opened socket\n");
int quit = 1;
while(quit == 1)
{
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR: could not connect\n");
close(sockfd);
exit(1);
}
fgets(buf, sizeof(buf), stdin);
if(strcmp(buf, "quit\n") == 0)
{
quit = 0;
int send;
send = sendto(sockfd, buf, MAX_LINE, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (send < 0)
error("ERROR: couldn't send data\n");
break;
}
int send;
send = sendto(sockfd, buf, MAX_LINE, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (send < 0)
error("ERROR: couldn't send data to server\n");
//receive data from server
send = recvfrom(sockfd, buf, MAX_LINE, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if(send < 0)
error("ERROR: couldn't receive from socket\n");
if(strcmp(buf, "quit\n") == 0)
quit = 0;
else
fputs(buf, stdout); //print what is received
}
}
This is the server side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAX_LINE 1024
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int clilen;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
portno = atoi(argv[1]);
//create a socket
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
clilen = sizeof(serv_addr);
if (sockfd < 0)
{
error("ERROR opening socket");
}
//bind address to socket
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR: could not bind");
//listen for connection request
listen(sockfd,5);
int quit = 1;
while(quit == 1)
{
if((newsockfd = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen))<0)
{
perror("Error: could no accept connection");
exit(1);
}
int n = recvfrom(newsockfd, buffer, MAX_LINE,0,(struct sockaddr *) &serv_addr,&clilen);
if(strcmp(buffer, "quit\n")== 0)
{
quit = 0;
break;
}
else
fputs(buffer, stdout);
//get data to be sent
fgets(buffer, MAX_LINE,stdin);
if(strcmp(buffer, "quit\n") == 0) //if quit is entered, terminate conn
{
quit = 0;
int n;
n = sendto(newsockfd, buffer, MAX_LINE,0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (n<0)
error("ERROR: could not send data");
break;
}
//send data
n = sendto(newsockfd, buffer, MAX_LINE, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (n<0)
error("ERROR sending data");
}
}
#user58697 is correct as to the proximate cause: last argument to sendto/recvfrom must be a pointer. However, I would add an additional note.
There's no point in using recvfrom/sendto in this program. You have a connected TCP socket; hence there's no reason to provide the sockaddr argument in each call. The addresses won't change, and you already know what they are (i.e. client knows its own address and specifies the address of the sender in the connect; server knows its own address and receives the client's address in the accept).
So once the connection is made, use the simpler send and recv functions instead. This will simplify your code and should simultaneously fix the problem.
You are making some big mistakes with this code, on both sides. Mostly bad socket management and bad buffer management. Try something more like this instead:
//Client side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5432
#define MAX_LINE 256
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char * argv[])
{
struct hostent *hp;
struct sockaddr_in serv_addr;
char *host;
char buf[MAX_LINE];
int sockfd, n;
if (argc != 2)
{
fputs("usage: simplex-talk host\n", stderr);
exit(1);
}
host = argv[1];
hp = gethostbyname(host);
if (!hp)
{
fprintf(stderr, "error: can't find such host: %s\n", host);
exit(1);
}
if (hp->h_addrtype != AF_INET)
{
fprintf(stderr, "error: host does not have an IPv4 address: %s\n", host);
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)hp->h_addr, (char *)&serv_addr.sin_addr.s_addr, hp->h_length);
serv_addr.sin_port = htons(SERVER_PORT);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR creating socket");
printf("successfully created socket\n");
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
fputs("ERROR: could not connect\n", stderr);
close(sockfd);
exit(1);
}
printf("successfully connected to server\n");
int quit = 0;
while (quit == 0)
{
fgets(buf, sizeof(buf), stdin);
if (strcmp(buf, "quit\n") == 0)
{
quit = 1;
n = send(sockfd, buf, strlen(buf), 0);
if (n < 0)
fputs("ERROR: couldn't send data to server\n", stderr);
break;
}
n = send(sockfd, buf, strlen(buf), 0);
if (n < 0)
{
fputs("ERROR: couldn't send data to server\n", stderr);
break;
}
//receive data from server
n = recv(sockfd, buf, sizeof(buf)-1, 0);
if (n < 0)
{
fputs("ERROR: couldn't receive from server\n", stderr);
break;
}
if (n == 0)
{
printf("server disconnected\n");
break;
}
buf[n] = 0;
if (strcmp(buf, "quit\n") == 0)
quit = 1;
else
fputs(buf, stdout); //print what is received
}
close(sockfd);
return 0;
}
// Server side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAX_LINE 256
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, clisockfd, portno, n;
char buffer[MAX_LINE];
struct sockaddr_in serv_addr, cli_addr;
int clilen;
if (argc < 2)
error("ERROR, no port provided");
portno = atoi(argv[1]);
//create a socket
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR creating socket");
//bind address to socket
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR: could not bind socket");
//listen for connection request
if (listen(sockfd, 5) < 0)
error("ERROR: could not listen on socket");
int quit = 0;
while (quit == 0)
{
clilen = sizeof(serv_addr);
clisockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (clisockfd < 0)
error("ERROR: could not accept connection");
while (quit == 0)
{
n = recv(clisockfd, buffer, sizeof(buffer)-1, 0);
if (n < 0)
{
fputs("ERROR: couldn't receive from client\n", stderr);
break;
}
if (n == 0)
{
printf("client disconnected\n");
break;
}
buffer[n] = 0;
if (strcmp(buffer, "quit\n") == 0)
{
quit = 1;
break;
}
fputs(buffer, stdout);
//get data to be sent
fgets(buffer, sizeof(buffer), stdin);
if (strcmp(buffer, "quit\n") == 0) //if quit is entered, terminate conn
{
quit = 1;
n = send(clisockfd, buffer, strlen(buffer), 0);
if (n < 0)
fputs("ERROR: could not send data to client\n", stderr);
break;
}
//send data
n = send(clisockfd, buffer, strlen(buffer)-1, 0);
if (n < 0)
{
fputs("ERROR sending data to client\n", stderr);
break;
}
}
close(clisockfd);
}
close(sockfd);
return 0;
}
Now, with that said, do note that TCP is a streaming transport. There is no 1-to-1 relationship between send() and recv() and no concept of messages, like this code assumes. The sender could send a message like "hello joe\n" and the receiver could read like "hello" " joe" "\n", depending on how TCP decides to break of the data during transmission. You really need to take that into account. Read raw bytes and append them to the end of a buffer. Check the buffer for a message terminator (in this case, \n). If found, process that complete message and remove it from the buffer. Repeat until there are no more terminators found in the buffer. Leaving unprocessed data in the buffer so it can be completed by subsequent reads.
I'll leave this as an exercise for you.