I am writing a private chat using UDP, but I have some problems while implementing the registration service. When the client writes the ID and password he wants to use, the server checks if the ID already exists(IDs and password are saved in a file), if it doesn't exist yet, the client can start chatting with other users(I still haven't implemented this part), if the ID is already in use I want to tell the user to choose another ID. In this scenario, I send the message "ID already in use" to the client using sendto but the recvfrom sometimes riceives other messages. Precisely the first time the user chooses a wrong ID, he receives the right message, then, if he chooses again an ID already in use, from the message he has received from the server he reads the ID he tried to choose and not the error message.The strangest thing is that at a third wrong attempt, the error message is correct.
Messages and related functions are defined in a file called utils.h
typedef struct Message{
int type; //Message's type: 0->registration; 1->login; 2->message; 3->ack
char* dest;
char* mitt; //source
char msg[1024];
}Message;
//createMsg is used to fill message struct
int createMsg(int type, char* dest, char* mitt, char * msg, struct Message* message){ //char msg[1024]
//printf("Sono in createMsg\n");
memset(message,0,sizeof(*message));
message->type = type;
message->dest = dest;
message->mitt = mitt;
//printf("msg to write: %s\n",msg);
strcpy(message->msg,msg);
//printf("msg written: %s\n",message->msg);
}
//print messages
void printMsg(struct Message* message){
if(strlen(message->msg)!=0) printf("type: %d, dest: %s, mitt:%s, msg: %s\n",message->type,message->dest,message->mitt,message->msg);
printf("dim msg tot: %lu\n",sizeof(*message));
printf("type dim: %lu, dest dim: %lu, mitt dim:%lu, msg dim: %lu, dim tot msg: %lu\n",sizeof(message->type),sizeof(message->dest),sizeof(message->mitt),strlen(message->msg),sizeof(message->msg));
}
//Set message's field to zero
void setToZeroMsg(struct Message* message){
message->type = 0;
message->dest = NULL;
message->mitt = NULL;
int i=0;
for(i=0;i<strlen(message->msg);i++){
message->msg[i]=0;
}
//memset(message->msg,0,strlen(message->msg));
}
This is the server:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h> // htons()
#include <netinet/in.h> // struct sockaddr_in
#include <sys/socket.h>
//#include "utente.h"
#include "utils.h"
#define MAX_CONNECTIONS 5
#define MAX_MESSAGE 1024
int main(){
int sockfd, ret;
char buffer[MAX_MESSAGE];
size_t buf_len = sizeof(buffer);
struct sockaddr_in server_addr, client_addr;
int serv_addr_len = sizeof(server_addr);
int client_addr_len = sizeof(client_addr);
//socket file descriptor
sockfd = socket(AF_INET, SOCK_DGRAM,0);
if(sockfd < 0){
perror("Errore nel creare la socket!");
exit(EXIT_FAILURE);
}
//Setting structure's content to zero
memset(&server_addr,0,serv_addr_len);
memset(&client_addr,0,client_addr_len);
//Server addr
server_addr.sin_family = AF_INET; //IPv4
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(5500);
//Bind
ret = bind(sockfd, (const struct sockaddr *)&server_addr, serv_addr_len);
if(ret < 0){
perror("Errore nella bind!");
exit(EXIT_FAILURE);
}
struct Message* newmsg = (struct Message*)malloc(sizeof(struct Message));
//Start comunication with clients
//int num_clients = 0;
while(1){
setToZeroMsg(newmsg); //Cancel previous messages
printf("waiting for a message from a client...\n");
//Receiving a message
ret = recvfrom(sockfd, newmsg, sizeof(*newmsg), 0, (struct sockaddr*)&client_addr, &client_addr_len);
if(ret == -1){
perror("Errore nella recvfrom!");
}
printMsg(newmsg);
int type = newmsg->type;
if(type == 0){ //Type==0 -> register request
printf("register request\n");
int newID = 0; //if is set to -1 the ID already exist
size_t msg_len=sizeof(newmsg->msg);
FILE* file = fopen("utenti.txt","r+");
if(file==NULL){
perror("Errore nell'apertura del file");
}
char* newuser = strcpy(newser,newmsg->msg);
strtok(newuser,";");
int size_newuser = sizeof(newuser);
while(1){
char* res = fgets(buffer,32,file);
if(res==NULL) break;
//printf("%s",buffer);
char* user = strtok(buffer,";");
//printf("%s\n",user);
int size_user = sizeof(user);
int size = (size_newuser > size_user)? size_newuser : size_user;
if(strncmp(newuser,user,size) == 0){
//printf("This name is already in use!\n");
/*memset(newmsg,0,sizeof(Message));
newmsg->type = 3;
newmsg->dest = NULL;
strcpy(newmsg->msg, "This ID is already taken!\n");
printf("mess: %s",newmsg->msg);*/
//Error message to client
creaMsg(3, NULL, NULL, "This ID is already taken!\n", newmsg); //buffer
printMsg(newmsg);
printf("msg: %s\n",newmsg->msg);
//ret = sendto(sockfd, (struct Message*)newmsg, sizeof(*newmsg), 0, (struct sockaddr*)&client_addr, (socklen_t) client_addr_len);
ret = sendto(sockfd,newmsg->msg,sizeof(newmsg->msg),0,(struct sockaddr*)&client_addr, (socklen_t) client_addr_len );
if(ret == -1){
perror("Errore nella sendto!");
exit(EXIT_FAILURE);
}
newID = -1;
break;
}
}
if(newID != -1){
ret = fprintf(file,newmsg->msg,msg_len);
if(ret == -1){
perror("Errore nella scrittura su file");
}
}
if(fclose(file) == -1) perror("Errore nella chiusura del file");
}
else if(type==1){
}
else if(type==2){
}
//This part is not implemented yet
/*ret = sendto(sockfd, buffer, buf_len,0,(const struct sockaddr*)&client_addr, (socklen_t) client_addr_len);
if(ret == -1){
perror("Errore nella sendto!");
}*/
}
close(sockfd);
return 0;
}
And this is the client file:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h> // htons()
#include <netinet/in.h> // struct sockaddr_in
#include <sys/socket.h>
//#include "utente.h"
#include "utils.h"
#define MAX_MESSAGE 1024
#define quit_command "QUIT"
int main(){
int sockfd, ret;
struct sockaddr_in server_addr;
int serv_addr_len = sizeof(server_addr);
char buffer[MAX_MESSAGE];
size_t buf_len = sizeof(buffer);
size_t msg_len;
int quit_command_len = strlen(quit_command);
//Message struct
struct Message message = {};
setToZeroMsg(&message);
//socket file descriptor
sockfd = socket(AF_INET, SOCK_DGRAM,0);
if(sockfd < 0){
perror("Errore nel creare la socket!");
exit(EXIT_FAILURE);
}
//Structures to zero
memset(&server_addr,0,serv_addr_len);
//Initialize server_addr
server_addr.sin_family = AF_INET; //IPv4
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(5500);
printf("Welcome in Private Chat!\n");
while(1){
char buf_credentials[32];
memset(buf_credentials,0,sizeof(buf_credentials));
memset(buffer,0,sizeof(buffer));
//setToZeroMsg(&message);
printf("If you want to register write 'r', to login type 'l':\n");
if (fgets(buffer, MAX_MESSAGE, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
if(!memcmp(buffer, "l", 1)){
printf("not implemented yet");
break;
}
else if(!memcmp(buffer,"r",1)){
printf("To register choose an ID and a password.\n");
printf("ID:\n");
if (fgets(buffer, 15, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
//printf("%s\n",buffer);
strncpy(buf_credentials,buffer,strlen(buffer)-1);
strcat(buf_credentials,";");
printf("Inserire password:\n");
if (fgets(buffer, 15, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
strcat(buf_credentials,buffer);
printf("utente+pass: %s",buf_credentials);
//Message struct
/*
struct Message message = {
};*/
setToZeroMsg(&message);
strcpy(message.msg, buf_credentials);
//send ID e password to server
ret = sendto(sockfd, (struct Message*)&message, sizeof(message), 0, (struct sockaddr*)&server_addr, (socklen_t) serv_addr_len);
if(ret == -1){
perror("Errore nella sendto!");
continue;
}
setToZeroMsg(&message);
printf("msg: %s\n",message.msg);
//ret = recvfrom(sockfd, (struct Message*)&message, sizeof(message), 0, (struct sockaddr*)&server_addr, (socklen_t*)&serv_addr_len);
ret = recvfrom(sockfd, message.msg, sizeof(message.msg), 0, (struct sockaddr*)&server_addr, (socklen_t*)&serv_addr_len);
printMsg(&message);
printf("msg: %s\n",message.msg);
if(ret == -1){
perror("Errore nella recvfrom!");
}
continue;
}
else{ //User didn't type 'r' or 'l'
printf("Wrong, you have to type 'r' o 'l'\n");
}
memset(buffer,0,MAX_MESSAGE);
}
//Chatting with server
while(1){
memset(buffer,0,MAX_MESSAGE);
printf("Type the message for the server, QUIT to leave the chat:\n");
if (fgets(buffer, MAX_MESSAGE, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
printf("You wrote: %s\n", buffer);
msg_len=strlen(buffer);
//Send Message
ret = sendto(sockfd, buffer, MAX_MESSAGE, 0, (struct sockaddr*)&server_addr, (socklen_t) serv_addr_len);
if(ret == -1){
perror("Errore nella sendto!");
continue;
}
//Server wrote back
memset(buffer,0,MAX_MESSAGE);
ret = recvfrom(sockfd, buffer, buf_len, 0, (struct sockaddr*)&server_addr, &serv_addr_len);
if(ret == -1){
perror("Errore nella recvfrom!");
}
printf("Message received from server: %s\n",buffer);
//Controlla se il messaggio ricevuto รจ QUIT
if (msg_len == quit_command_len+1 && !memcmp(buffer, quit_command, quit_command_len)) break;
}
printf("Closing connection!\n");
close(sockfd);
return 0;
}
ID and password are stored in the file "utenti.txt", separated by semicolons, in this way:
ID1;password1
ID2;password2
...
I hope I have been clear about my problem, thank you for helping me!
Related
I've just started taking network programming classes and this is what we did in class in order to make connection between client and server. My problem is that I cannot connect to the server, it just stops after printing "addrinfo is successful" and does not loop through.
We used 8080 for port number in class and that did not work, so I tried using 7070 and it worked maybe 1 out of 50 times. I don't have any problems with the client side of the program, it works completely fine. I'm using Visual Studio Code on MacBook if that makes any difference, I also tried using the terminal but that did not work either.
//client to server
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
int main(){
const char *hostname = "127.0.0.1";
const char *portNumber = "7070";
int clientSocket; //socketFD
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
struct addrinfo *results; // const for head
struct addrinfo *record; // temp for traversing
int error;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(hostname, portNumber, &hints, &results);
// error checking
if(error >= 0){
printf("Client: getaddressinfo() successful\n ");
}
//traversing the list
for(record = results; record != NULL; record = record->ai_next){
clientSocket = socket(record->ai_family, record->ai_socktype, 0);
if(clientSocket == -1){
continue;
}
if(connect(clientSocket, record->ai_addr, record-> ai_addrlen) != -1){
break;
}
close(clientSocket);
}
//socket() and connect() both were success
//send()
if(record == NULL){
printf("Error\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(results);
printf("socket status: created and connected\n");
char *message = "Hello" ;
if(send(clientSocket, message, strlen(message), 0) == -1){
printf("Error\n");
exit(EXIT_FAILURE);
}
else{
printf("Message sent successfuly\n");
}
close(clientSocket);
return 0;
}
//server
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
int main(){
printf("Starting the server\n");
const size_t bufferSize = 1024;
const char *portNumber = "7070";
const int backlog = 1;
int serverSocket;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo *results;
struct addrinfo *record;
if((getaddrinfo(NULL, portNumber, &hints, &results)) != 0){
printf("Error\n");
exit(EXIT_FAILURE);
}
printf("addrinfo is successful\n");
//traverse through the list
for(record = results; record != NULL; record = record->ai_next){
serverSocket = socket(record->ai_family, record->ai_socktype, record->ai_protocol);
if(serverSocket == -1){
continue;
}
int enable = 1;
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if(bind(serverSocket, record->ai_addr, record->ai_addrlen) == 0){
break;
}
close(serverSocket);
}
if(record == NULL){
exit(EXIT_FAILURE);
}
freeaddrinfo(results);
printf("Socket status: created and binded successfuly\n");
if(listen(serverSocket, backlog) == -1){
printf("ERROR\n");
exit(EXIT_FAILURE);
}
printf("Server is listening\n");
while(1){
int clientSocket;
struct sockaddr clientAddress;
socklen_t clientAddressLength = sizeof(clientAddress);
if((clientSocket = accept(serverSocket, &clientAddress, &clientAddressLength)) <0){
printf("Error\n");
exit(EXIT_FAILURE);
}
printf("Client socket accepted\n");
char buffer[bufferSize];
if(recv(clientSocket, buffer, sizeof(buffer), 0) == -1){
printf("Error\n");
exit(EXIT_FAILURE);
}
printf("Message is received: %s\n", buffer);
close(clientSocket);
printf("Client socket is closed\n");
}
return 0;
}
I have been trying to write a client and server program using C socket programming that does 2 tasks
On prompted from server -> OS command is executed in client machine
Output is stored in a file which is sent back to server. Where server reads it and displays the data plus writes the data in a file on server side.
Issue
When client sends file to the server, server does not display whole data and looks like recv() keeps waiting on socket.
Need some help
Here's the code
server 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 <arpa/inet.h>
#define SIZE 1024
void write_file(char *filename,int sockfd){
int n;
FILE *fp ;
char buffer[SIZE] ;
fp = fopen(filename, "w");
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0){
break;
return;
}
printf("%s", buffer) ;
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
fclose(fp) ;
return;
}
int main(int argc, char *argv[]){
int portno = 7416;
int e,n,n1;
char *cmd ;
int sockfd;
struct sockaddr_in server_addr;
struct hostent *server;
char *fle = "/tmp/reposvr.";
FILE *fp;
char *num ;
if (argc < 3) {
fprintf(stderr,"usage %s hostname command \n", argv[0]);
exit(0);
}
cmd=argv[2] ;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
//server_addr.sin_family = AF_INET;
//server_addr.sin_port = port;
//server_addr.sin_addr.s_addr = inet_addr(ip);
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portno);
server_addr.sin_addr = *((struct in_addr *)server->h_addr);
memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero);
e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e == -1) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Connected to Server.\n");
n = write(sockfd, cmd , strlen(cmd));
if (n < 0)
error("ERROR writing to socket");
char *filename=NULL;
filename = (char*)malloc( 50 * sizeof(char) ) ;
strcpy(filename,fle );
n1=rand();
if (asprintf(&num, "%d", n1) == -1) {
perror("asprintf");
} else {
strcat(filename, num);
printf("%s\n", filename);
free(num);
}
printf("%s\n",filename) ;
write_file(filename,sockfd) ;
printf("[+]File data sent successfully.\n");
printf("[+]Closing the connection.\n");
close(sockfd);
return 0;
}
Client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024
void send_file(FILE *fp, int sockfd){
int n;
char data[SIZE] = {0};
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
int main(){
int port = 7416;
int e,n1, n ;
FILE *fp ;
char filename[50] = "/tmp/gateway." ;
char command[50];
char *num;
FILE *pf;
char data[SIZE];
int sockfd, new_sock;
struct sockaddr_in server_addr, new_addr;
socklen_t addr_size;
char buffer[SIZE];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
e = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e < 0) {
perror("[-]Error in bind");
exit(1);
}
printf("[+]Binding successfull.\n");
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
perror("[-]Error in listening");
exit(1);
}
addr_size = sizeof(new_addr);
while ( new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size) )
{
printf("server: got connection from %s port %d\n",
inet_ntoa(new_addr.sin_addr), ntohs(new_addr.sin_port));
n = read(new_sock,buffer,1024);
if (n < 0) error("ERROR reading from socket");
strcpy(command, buffer) ;
printf("%s",command) ;
pf = popen(command,"r");
bzero(data,1024);
n1=rand();
if (asprintf(&num, "%d", n1) == -1) {
perror("asprintf");
} else {
strcat(filename, num);
printf("%s\n", filename);
free(num);
}
printf("%s",filename) ;
fp=fopen(filename,"w" );
while (fgets(data, 2048, pf) != NULL) {
printf("%s", data);
fprintf(fp, "%s",data) ;
}
fclose(fp) ;
fp = fopen(filename, "r");
if (fp == NULL) {
perror("[-]Error in reading file.");
exit(1);
}
send_file(fp, new_sock);
printf("[+]Data written in the file successfully.\n");
}
return 0;
}
Execution output
Edit
Based on the suggestions in this forum, I increased SIZE to 2048 and found that now it returns less rows and hangs after 4-5 rows itself. This is weird. I am sure it's not because of SIZE.
If you see, in client side, we are able to successfully write all in a file. Second part of the program is to read from file and send it to server. Here I am iterating through whole file and sending the data to server. The data send loop is working nicely as I have printf in same loop and we can see all data getting printed.
Looking at server side, here also we are looping till number of bytes read are < 1. Theoretically, this should work. I am sure there's some tiny silly thing that I am missing. Just not able to put my finger on it. Really need some insights in here.
Edit 2
Already tried SIZE , MSG_PEEK as you can see in comments. Any more suggestions ?
I have a server program here that checks the input sent from the client and returns a message back to the client wether the password is right or wrong .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Practical.h"
#include <unistd.h>
#include <sys/stat.h>
#define BUFSIZE 200
int main(int argc, char* argv[])
{
int numBytes = 0;
int MAXPENDING = 1;
char recvbuffer[BUFSIZE], sendbuffer[BUFSIZE];
char inp_user[BUFSIZE];
char inp_pass[BUFSIZE];
char pass[BUFSIZE] = "pass";
char user[BUFSIZE] = "admin";
int attemptsLeft = 3;
if (argc != 2)
DieWithUserMessage("Parameter(s)", "<Server Port>");
in_port_t servPort = atoi(argv[1]);
int servSock;
if ((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithSystemMessage("socket() failed");
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);
if (bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("bind() failed");
//accept incoming connection requests to the server socket
//MAXPENDING is the maximum number of connections
//that should be queued for this socket
if (listen(servSock, MAXPENDING) < 0)
DieWithSystemMessage("listen() failed");
for (;;)
{
//declare client address structure
struct sockaddr_in clntAddr;
socklen_t clntAddrLen = sizeof(clntAddr);
//return new file descriptor referring
//to the client socket , all read/write operations will be
//performed on this socket
int clntSock = accept(servSock, (struct sockaddr *) &clntAddr, &clntAddrLen);
//check if the client socket has not been created
if (clntSock < 0)
DieWithSystemMessage("accept() failed");
//retrieve the data sent by the client
while ((numBytes = recv(clntSock, recvbuffer, (BUFSIZE-1), 0)) > 0) {
recvbuffer[numBytes] = '\0';
fputs(recvbuffer, stdout);
// if(strstr(recvbuffer, "\r\n\r\n") > 0)
// break;
}
//check if data has not been received from the client
if (numBytes < 0)
DieWithSystemMessage("recv() failed");
//read username and password into the server's buffers
sscanf(recvbuffer, "%s %s", inp_user, inp_pass);
//check if the entered username and pasword is correct
if( (strcmp(user, inp_user) == 0)
&&
(strcmp(pass, inp_pass) == 0)
)
{
snprintf(sendbuffer, sizeof(sendbuffer), "%s", "PROCEED\r\n");
}
else //the credentials entered were incorrect
{
attemptsLeft--;
//check if user has no attempts left
if(attemptsLeft == 0) {
snprintf(sendbuffer, sizeof(sendbuffer), "%s", "DENIED\r\n" );
} else {
snprintf(sendbuffer, sizeof(sendbuffer), "%s", "NONO\r\n");
// "You have %d attempt(s) left", attemptsLeft);
}
}
printf("The send message contains %s \n\n", sendbuffer);
printf("brefore sending\n");
ssize_t numBytesSent = send(clntSock, sendbuffer, strlen(sendbuffer), 0);
printf("after sending\n");
if (numBytesSent < 0)
DieWithSystemMessage("send() failed");
printf("NOBYTES: %d", numBytes);
close(clntSock);
}
}
The message contains prints successfully meaning a message is created for the user however the send() function is never called and the client never receives this message. Anyone know why this would happen?
I have code for a server that can handle multiple clients. The client program can connect to the server and issue Unix commands such as ls, date, clear, etc. I have two problems that I cannot figure out. 1) When I initially type ls as an argument it will return some weird garbage, and then if I do ls again then it starts working properly. So only in the beginning, it will give me garbage. 2) When I type the argument 'ps -ael' into the terminal, it will work properly, but then after that I get a 'Failed' message, which is coming from the Client code, specifically at the while(1) loop where if (send(clientSocket, s, echolen, 0) != echolen), this is where the error is occurring. I was curious to know if someone could point to what the problem could be, I think it might be because I create a char array that's too big but I'm not sure.
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUFFSIZE 2048
int main(int argc, char *argv[]){
int clientSocket, ret, portnum;
struct sockaddr_in serverAddr;
int received = 0;
unsigned int echolen;
char buffer[1024];
if(argc < 3){
fprintf(stderr,"usage %s <server-ip-addr> <server-port>\n", argv[0]);
exit(0);
}
portnum = atoi(argv[2]);
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Client Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
// memset(&buffer, '\0', sizeof(buffer));
// serverAddr.sin_family = AF_INET;
// serverAddr.sin_port = htons(PORT);
// serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// bzero((char *) &serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
if(!inet_aton(argv[1], &serverAddr.sin_addr)){
fprintf(stderr, "Error invalid server IP address\n");
exit(1);
}
serverAddr.sin_port = htons(portnum);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Connected to server.\n");
char s[100];
while(1){
fgets(s, 100, stdin);
s[strlen(s)-1]='\0';
echolen = strlen(s);
/* send() from client; */
if (send(clientSocket, s, echolen, 0) != echolen)
{
printf("Failed");
}
if(strcmp(s,"exit") == 0) // check if exit is typed
exit(0);
fprintf(stdout, "Message from server: ");
while (received < echolen)
{
int bytes = 0;
/* recv() from server; */
if ((bytes = recv(clientSocket, buffer, echolen, 0)) < 1)
{
printf("Failed to get Information");
}
received += bytes;
buffer[bytes] = '\0';
fprintf(stdout, buffer);
}
int bytes = 0;
do {
buffer[bytes] = '\0';
printf("%s\n", buffer);
} while((bytes = recv(clientSocket, buffer, BUFFSIZE-1, 0))>=BUFFSIZE-1);
buffer[bytes] = '\0';
printf("%s\n", buffer);
printf("\n");
}
}
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUFFSIZE 2048
#define MAX 2048
void setup(char inputBuffer[], char *args[], int *background){
const char s[4] = " \t\n";
char *token;
token = strtok(inputBuffer, s);
int i = 0;
while(token != NULL){
args[i] = token;
i++;
token = strtok(NULL, s);
}
args[i] = NULL;
}
void HandleClient(int sock){
char buffer[BUFFSIZE];
int received = -1;
char data[MAX];
memset(data, 0, MAX);
while(1){
data[0] = '\0';
if((received = recv(sock, buffer, BUFFSIZE, 0)) < 0){
printf("Error");
}
buffer[received] = '\0';
strcat(data, buffer);
if(strcmp(data, "exit") == 0){
exit(0);
}
puts(data);
char *args[100];
setup(data, args, 0);
int pipefd[2], length;
if(pipe(pipefd)){
printf("failed to create pipe");
}
pid_t pid = fork();
char path[MAX];
if(pid==0)
{
close(pipefd[0]); // close the readonly side of the pipe
//close(1); // close the original stdout
dup2(pipefd[1],1); // duplicate pipfd[1] to stdout
dup2(pipefd[1], fileno(stderr));
//close(pipefd[0]); // close the readonly side of the pipe
close(pipefd[1]); // close the original write side of the pipe
printf("before execvp");
execvp(args[0],args); // finally execute the command
// exit(0);
}
else
if(pid>0)
{
close(pipefd[1]);
memset(path,'\0',MAX);
while(length=read(pipefd[0],path,MAX-1)){
//printf("Data read so far %s\n", path);
if(send(sock,path,strlen(path),0) != strlen(path) ){
printf("Failed");
}
fflush(NULL);
//printf("Data sent so far %s\n", path);
memset(path,0,MAX);
}
close(pipefd[0]);
//exit(1); removed so server will not terminate
}
else
{
printf("Error !\n");
exit(0);//
}
}
}
int main(){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Server Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding");
exit(1);
}
printf("Bind to port %d\n", 4444);
if(listen(sockfd, 10) == 0){
printf("Listening....\n");
}else{
printf("Error in binding.\n");
}
while(1){
newSocket = accept(sockfd, (struct sockaddr*) &newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
//worker
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
if(strcmp(buffer, ":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
}else{
printf("Client: %s\n", buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
HandleClient(newSocket);
}
}
}
close(newSocket);
return 0;
}
I am trying to implement a simple HTTP server with C that
reads a request
checks if it is a GET request
reads the URL from the request
Checks if file is on server and tries to open it
I am using strtok for String tokenizing and I think it messes up the filepath. open and fopen always return error codes and are not able to open any files.
Here is my code:
/*
** parser.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 3499 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXLEN 1024 //upper limit of the length of the string
int main(void)
{
char input[MAXLEN]; //the line that is read from the client
char * token1; //GET request
char * token2; //filepath
char tmpstring[MAXLEN]; //filesize
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd, file open on file_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
int sin_size;
int yes=1;
int n; //the amount of read characters from the client
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
while(1) { // main accept() loop
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
n = readline(new_fd, input, MAXLEN); //n is the amount of read characters
if (n == -1) {
perror("Unable to read line");
}
//Check if it is a GET message
token1 = strtok(input," ");
if(strcmp(token1, "GET") != 0)
{
send(new_fd, "Bad request\n", 30, 0);
}
else
{
//Retrieve the file path
token2 = strtok(NULL, " ");
if(token2 == NULL)
{
send(new_fd, "File path not specified\n", 23, 0); //Check if filename is empty
}
send(new_fd, token2, strlen(token2), 0); //test
printf("%s", token2);
if(token2[0] == '/') //remove the initial slash
memmove(token2, token2 + 1, strlen(token2));
//char * path = "test.html"; //test line
//char * buff;
//int len = sprintf(buff, "1: %d 2: %d\n", strlen(token1), strlen(token2));
//send(new_fd, buff, len, 0);
//Check if file is on the server
if(open(token2, O_RDONLY) < 0) //Error opening file
{
if(errno == EACCES)
send(new_fd, "Access error\n", 30, 0);
else
send(new_fd, "Not existed\n", 30, 0);
}
else
{
FILE * requested_file = fopen(token2, "r");
if(requested_file == NULL) //
{
send(new_fd, "Error in fopen\n", 30, 0);
}
else
{
send(new_fd, "File found\n", 30, 0); //successful
}
fseek(requested_file, 0, SEEK_END); // move to the end of the file
int end= ftell(requested_file); // get the position of the end of file
int stringlen = sprintf(tmpstring, "file size: %d\n", end);
send(new_fd, tmpstring, stringlen, 0);
}
}
close(new_fd); //close connection
}
return 0;
}
//helper function for recieving text
int readline(int fd, char *buf, int maxlen)
{
int n, rc;
char c;
for (n = 1; n < maxlen; n++) {
if ((rc = read(fd, &c, 1)) == 1) {
*buf++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
if (n == 1)
return 0; // EOF, no data read
else
break; // EOF, read some data
} else
return -1; // error
}
*buf = '\0'; // null-terminate
return n;
}
So I'm placing a test.html in the same folder as the server. Then im telnetting to localhost and port 3499. This is the output when entering GET /test.html:
/test.html
Not existed
rError in fopen
Connection closed by foreign host.
try opening "test.html" instead of "\test.html"