C multisocket program not working - c

I am trying to create a simple client/server socket-based program. It's just a basic "Guess the number" game, where the server comes up with a number and then the client(s) try to guess the number. The problem is that I am having problems with the programs working as intended.
The problem is such: When I launch up the server program and it generates the random number, I try loading up the client programs, but after one input, they stop working. It stops after outputting this:
Guess: 42
Buffer to be processed : <42
>
integerGuess : <42>
String Guess : <42\n>
Buffer to send : <42\n>
Here's the server.c file 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>
#include <time.h> /* time for randomizer*/
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, n;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int GuessedInteger, integerRandom, serverFlagCorrect;
char charGuess[4], answerServer[1];
char* delimiter = "\\n";
/** initialization of variables **/
serverFlagCorrect = 0;
/** generate random integer from 1 to 100 **/
srand (time(NULL));
integerRandom = (rand() % 100) + 1;
printf("This is the random integer : %d \n", integerRandom);
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
// Creates the socket socket() --> endpoints of sockets
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
// Creates the socket socket() --> endpoints of sockets
// assign unique new address
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");
// assign unique new address
// wait for a connection
listen(sockfd,5);
// wait for a connection
// accepts the connection
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
n = fork();
if (n < 0)
error("ERROR on fork");
if (n == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
void dostuff (int sock) {
int GuessedInteger, integerRandom, serverFlagCorrect;
char charGuess[4], answerServer[1];
char* delimiter = "\\n";
int sockfd, newsockfd, portno, n;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
while (serverFlagCorrect != 1)
{
// reads the data being received
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
// reads the data being received
printf("Buffer from client: <%s>\n", buffer);
memcpy(charGuess, buffer, sizeof(charGuess));
printf("Message from client in charGuess: <%s>\n", charGuess);
/* Put if statement here for error out if no \n at the end */
int len = strlen(charGuess);
const char *last_two = &charGuess[len-2];
printf("Last two characters of charGuess: <%s>\n", last_two);
if (strncmp ( last_two, delimiter, 2) )
error (" ERROR Wrong protocol received");
/** turn string to int for comparison **/
GuessedInteger = atoi(charGuess);
printf("Guessed Integer : %d \n", GuessedInteger);
/** Server response for comparison**/
if (GuessedInteger > integerRandom)
memcpy(&answerServer, "Lower", sizeof(answerServer));
else if (GuessedInteger < integerRandom)
memcpy(&answerServer, "Higher", sizeof(answerServer));
else if (GuessedInteger == integerRandom)
{
serverFlagCorrect = 1;
memcpy(&answerServer, "Correct", sizeof(answerServer));
}
printf("Value of answerServer: %c\n", *answerServer);
/** Server response for comparison**/
// sends the answer
n = write(newsockfd, answerServer, 1);
if (newsockfd < 0)
error("ERROR on accept");
// sends the answer
// closes what was sent
}
close(newsockfd);
}
Here's the client.c 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;
char buffer[1024];
int integerGuess, clientFlagCorrect;
int numberOfTries;
char charGuess[1024], answerServer[1];
char* delimiter = "\\n";
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
// Creates the socket socket() --> endpoints of sockets
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
// Creates the socket socket() --> endpoints of sockets
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
// connects to the service in connect()
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");
// connects to the service
/** variables **/
clientFlagCorrect = 0;
numberOfTries = 0;
while (clientFlagCorrect != 1)
{
numberOfTries = numberOfTries + 1;
/** initializing vars **/
integerGuess = 0;
memset(charGuess, 0, sizeof(charGuess));
// ask for the number
printf("Guess: ");
bzero(buffer,sizeof(buffer));
fgets(buffer,sizeof(buffer)-1,stdin);
printf("Buffer to process is : <%s>\n", buffer);
// ask to see if the number is guessed
/** string and delimeter **/
integerGuess = atoi(buffer);
printf("int Guess : <%d> \n", integerGuess);
sprintf( charGuess, "%d", integerGuess);
strcat( charGuess, delimiter);
printf("String Guess : <%s> \n", charGuess);
memset(buffer,0,sizeof(buffer));
memcpy(buffer, charGuess, sizeof(charGuess));
printf("Buffer to be sent is: : <%s>\n",buffer);
/** process the integer to string and add a delimiter **/
// send the string that was processed
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
// send the string that was processed
// reads the data being received
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
// reads the data being received
printf("Buffer received : <%s>\n",buffer);
memcpy(&answerServer, buffer, sizeof(answerServer));
printf ("Value of answerServer : <%c> \n", *answerServer);
/** Client response **/
if (strncmp ( & answerServer[0],"Lower",sizeof(answerServer)) == 0)
printf("The number is lower \n");
else if (strncmp ( & answerServer[0],"Higher",sizeof(answerServer)) == 0)
printf("The number is higher \n");
else if (strncmp ( & answerServer[0],"Correct",sizeof(answerServer)) == 0)
{
printf("Your guess is correct! \n");
clientFlagCorrect = 1;
}
else
error("ERROR Wrong message received");
}
printf ("It took you this many tries: %d \n", numberOfTries);
printf("%s\n",buffer);
close(sockfd);
return 0;
}
Any help would be greatly appreciated.
EDIT: After some extra work and "Debugging" (consisting mostly of me adding a load of printf's at various points) I am 90% convinced the problem is on the server side. I added printf's before and after this line:
printf("This is the random integer : %d \n", integerRandom);
And found that while the printf immediately before the line prints out fine, placing one right below it only prints it if prints out the "No port detected" error. Any further printf's don't trigger at all, which means that the program doesn't even reach the main loop that does the program.
As for the client file, it reached the line:
printf("Buffer to be sent is: : <%s>\n",buffer);
And stops (Once again via printf's). Why, I honestly have no clue. Which means there's a problem somewhere around those points, but where, I honestly have no clue.

Related

Server delay on system command in C

I have two programs, one acting as a server and one acting as a client. They are supposed to act like you are connecting to remote system using ssh. The client sends a command and the server executes the command and prints the output to the server. Although my code does exactly that, there is a delay on the output after the first command. For example if the client sents date, the server will return the date. If the client sends date again it will print message was received but not the output. On the third input from client, the second date will be executed and print on the client Here is the message:date and so on. Any ideas would be really apreciated.
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_PINS 1
void error(const char *msg){
perror(msg);
exit(1);
}
void exec_comm(int sock,int nerror,char buff[]){
dup2(sock,1);
dup2(nerror,2);
if(system(buff)==-1){
printf("command not found\n");
}
}
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,done=0,correct=0;
char str[INET_ADDRSTRLEN];
char* args,*pins[MAX_PINS]={"1234"},pin[10];
FILE* fd;
int nerror;
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");
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);
sscanf(buffer,"%s\n",buffer);
printf("The message that was read was:\t%s\n",buffer);
if (n < 0) error("ERROR reading from socket");
fprintf(fd,"%s\n",buffer);
if(strcmp(buffer,"exit\n")==0||strcmp(buffer,"exit")==0){
printf("Exiting...\n");
done=1;
break;
}
exec_comm(newsockfd,nerror,buffer);
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "message received", 17);
if (n < 0) error("ERROR writing to socket");
}
fclose(fd);
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");
n = write(sockfd, stdin, sizeof(int));
if (n < 0)
error("ERROR writing to socket");
do{
printf("Please enter the message: ");
bzero(buffer, 256);
fgets(buffer, 255, stdin);
if(strcmp(buffer,"exit\n")==0||strcmp(buffer,"exit")==0){
printf("Exiting...\n");
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
close(sockfd);
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;
}
n = write(sockfd, buffer, strlen(buffer));
That's your problem right here. Calls to write do not result in individual distinguishable messages, one message per call. They result in a single homogenous stream (that's the "stream" in SOCK_STREAM) of bytes with no delimiters.
You have newlines that separate commands, which is nice and all, but read has no idea about newlines. It will just wait until the buffer is full, or enough time has passed, or whatever. You have no control over it.
You basically have 2 ways to fix this.
Read character by character (pass the length of 1) and stop as soon as you see a newline. Accumulate the characters in a buffer, then execute it.
Send the length of each message before the message itself, in a fixed-length record, so that the server can safely read the length and then use it to read the message itself.

How to convert char[ ] to char *?

I'm wondering how to convert a char[] array to a char *
For example, in my code I am trying to access a web server using a hostname like "example.com"
Using my code, if I set a char * to "example.com" like below, it works perfectly.
char *host = "example.com";
But, what I really want to do is be able to read from a client program using a socket, write to a char[] array, and use the data obtained from that as the hostname.
For example,
char buffer[4096], hostname[4096];
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
wbhost = gethostbyname(hostname);
when my code gets to the last line, it just sits there, so I'm thinking its a typing problem, since when I do this:
char *host = "example.com";
...
wbhost = gethostbyname(host);
It works, and is able to get the data from the web and send it properly to my client program.
Any ideas are appreciated.
In the client program I use fgets() to read into a char[] from stdin then use write() to write to the socket for the server program to read. I had tried to use strcat() to add '\0' to the end of the char[] before writing to the socket but that didn't seem to do anything
Full Code: (Please ignore the comments, just trying different things for now)
client
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int sockfd, portnum, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[4096];
if(argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
portnum = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("ERROR opening Socket");
exit(1);
}
server = gethostbyname(argv[1]);
if(sockfd == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(1);
}
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(portnum);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR, on connecting");
exit(1);
}
printf("Please enter the Host name: ");
bzero(buffer, 4096);
fgets(buffer, 4095, stdin);
//strcat(buffer, "\0");
n = write(sockfd, buffer, strlen(buffer));
if(n < 0)
{
printf("Error writing to socket");
exit(1);
}
bzero(buffer, 4096);
n = read(sockfd,buffer, 4095);
if(n < 0)
{
printf("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
server
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portnum, clilen;
char buffer[4096], hostname[4096];
pid_t p_id;
struct sockaddr_in serv_addr, cli_addr;
int n, pid, hostname_len;
//char *host;
char *host = "example.com";
if(argc < 2)
{
fprintf(stderr, "ERROR, NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);//socket is made
if(sockfd < 0)
{
fprintf(stderr, "ERROR opening socket!!");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portnum = atoi(argv[1]);//port num
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnum);
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR on binding");
exit(1);
}
if( listen(sockfd, 5) < 0)
{
printf("ERROR ON LISTEN");
exit(1);
}
// accept
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if(newsockfd < 0)
{
fprintf(stderr, "ERROR on accept\n");
exit(1);
}
pid = fork();
if(pid == 0)
{
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
if(n < 0)
{//message from client
fprintf(stderr, "ERROR Reading from socket\n");
exit(1);
}
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
//variables used for acsessing webserver?
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
if(sockwb < 0)
{
printf("Error opeing websocket\n");
exit(1);
}
// hostname_len = sizeof(hostname) / sizeof(hostname[0]);
// printf("%d\n", hostname_len);
// memcpy(host, hostname, hostname_len);
// host[hostname_len] = '\0';
printf("%s\n", host);
// hostname[hostname_len] = '\0';
// host = &hostname[0];
//wbhost = gethostbyname(hostname);
wbhost = gethostbyname(host);
//printf("%s", wbhost->h_name);
printf("here2\n");
/*if(wbhost == NULL)
{
printf("NO SUCH web HOST\n");
exit(1);
}
*/
bzero((char*) &webser_addr, sizeof(webser_addr));
webser_addr.sin_family = AF_INET;
bcopy((char *)wbhost->h_addr, (char *)&webser_addr.sin_addr.s_addr, wbhost->h_length);
webser_addr.sin_port = htons(wbport);
// printf("here3\n");
if(connect(sockwb, (struct sockaddr *) &webser_addr,sizeof(webser_addr)) < 0)
{
printf("Error on web connecting\n");
exit(1);
}
bzero(webbuf, 4096);
strcpy(webbuf, "GET / HTTP/1.0\r\nHost: ");
// strcat(webbuf, hostname);
strcat(webbuf, host);
strcat(webbuf, "\r\nConnection: close\r\n\r\n");
// const char * request = "GET / HTTP/1.0\r\nHost: example.com\r\nConnection: close\r\n\r\n";
// printf("%s\n", request);
// x = write(sockwb, request, strlen(request));
printf("%s\n", webbuf);
x = write(sockwb, webbuf, strlen(webbuf));
if(x < 0)
{
printf("Error writing to web sock");
exit(1);
}
bzero(webbuf, 4096);
x = read(sockwb, webbuf, 4096);
if(n < 0)
{
printf("Error reading from web socket");
exit(1);
}
printf("%d\n", (int)strlen(webbuf));
printf("%s\n",webbuf);
n = write(newsockfd, webbuf, 4095 );//write back to client
if(n < 0)
{
fprintf(stderr, "ERROR WRITING to socket");
exit(1);
}
//printf("%s\n", webbuf);
}//end of if pid==0
printf("closing client");
close(newsockfd);//closing client socket
}while(1);
return 0;
}
The code you posted runs unimpeded. When you ask for help, you should always post a complete, verifiable example. Check that the code you post actually reproduces the problem!
Looking at what the code does, it seems that in the server, you meant to use the host name that you read as the argument to gethostbyname. You can do that with
host = &hostname[0];
or simpler
host = hostname;
or by not using two separate variables in the first place.
When you use an array in a context that expects a value (as opposed to e.g. taking its address or its sizeof), the array decays into a pointer to its first element. So here hostname is equivalent to hostname[0].
After that change, check the trace closely, or, to make the problem more visible, change the tracing line to
printf("[%s]\n", hostname);
You'll see
[aaa.com
]
The client reads a line with fgets, which includes the terminating newline character in its count. The client dutifully forwards the complete line to the server. And so the server looks up a host name containing a newline character, which doesn't exist. You don't check the return code of gethostbyname (you should!), it returns a null pointer, and the program crashes when it tries to read from it.
#Gilles is right, you have an '\n' at the end of the hostname, the following piece of code replaces the '\n' by 0 which is the equivalent of the character '\0':
extern int h_errno;
...
hostname[strlen(hostname) - 1] = 0;
wbhost = gethostbyname(hostname);
if (!wbhost) {
printf("Failed! %s\n", strerror(h_errno));
exit(1);
}
...
A char[] is an array of chars. A char* is a pointer to a char - generally (but not always) the start of a string.
If you want to get a pointer to the start of your array, you don't even need to do anything! This conversion happens implicitly:
char hello[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
// or: char hello[] = "hello"; (equivalent to above)
printf("%s", hello); // prints hello
puts(hello); // also prints hello
char *hello2 = hello;
puts(hello2); // also prints hello
Probably the easiest way to 'convert' char[] to char * is:
char example_array[] = "example";
char * example_pointer = (char *)calloc(1, strlen(example_array) + 1); // + 1 for the '\0' character
strcpy(example_pointer, example_array);

Socket multithreading Implementation C

I am working on a implementing a multithread multi client single server socket in C. However for whatever reason currently the program, when using pthread_create() to create a new thread, it does not advance past that line of code. I have put print lines before and after this line of code and all of the print lines before hand print fine but none of them after print. This leads me to believe that pthread_create() is somehow buggy. The strange thing about this is I can have 1 client connect and successfully sent/receive data from the server but because the loop that the listen() command is in is not advancing I cannot take on additional clients. I appreciate your help in this matter.
Server Code
#include <stdio.h>
#include <stdlib.h> //for IOs
#include <string.h>
#include <unistd.h>
#include <sys/types.h> //for system calls
#include <sys/socket.h> //for sockets
#include <netinet/in.h> //for internet
#include <pthread.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
void *threadFunc(int mySockFd)
{
int n;
char buffer[256];
do
{
bzero(buffer,256);
n = read(mySockFd,buffer,255);
if (n < 0)
{
error("ERROR reading from socket");
}
else if(strcmp(buffer, "EXIT\n") == 0)
{
printf("Exit by user\n");
pthread_exit(NULL);
}
else
{
printf("Here is the message: %s\n",buffer);
n = write(mySockFd,"I got your message",18);
if (n < 0)
{
error("ERROR writing to socket");
}
}
}while(n >= 0);
}
int main(int argc, char *argv[])
{
int sockfd;
int newsockfd;
int portno;
pthread_t pth;
int n; /*n is the return value for the read() and write() calls; i.e. it contains the number of characters read or written.*/
int i = 0;
printf("after var decl");
socklen_t clilen; /*clilen stores the size of the address of the client. This is needed for the accept system call.*/
char buffer[256]; /*The server reads characters from the socket connection into this buffer.*/
struct sockaddr_in serv_addr;
struct sockaddr_in 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");
}
do
{
printf("before listen");
listen(sockfd,5);
printf("after listen");
clilen = sizeof(cli_addr);
printf("before accept");
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
printf("after accept");
pthread_create(&pth,NULL,threadFunc(newsockfd),(void*) &i);
printf("after pthread create");
if (newsockfd < 0)
{
error("ERROR on accept");
}
}while(1 == 1);
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0)
{
error("ERROR reading from socket");
}
printf("Here is the message: %s\n",buffer);
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
and here is the 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> /*The file netdb.h defines the structure hostent, which will be used below.*/
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd;
int portno;
int 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);
n = write(sockfd,buffer,strlen(buffer));
if(strcmp(buffer,"EXIT\n") == 0)
{
printf("Connection Terminated\n");
break;
}
if (n < 0)
{
error("ERROR writing to socket");
}
bzero(buffer,256);
n = read(sockfd,buffer,255);
printf("%s\n",buffer);
if (n < 0)
{
error("ERROR reading from socket");
printf("%s\n",buffer);
}
}while(1 == 1);
close(sockfd);
return 0;
}
Two errors:
You are casting too much, the only place here should be the inaddr stuff.
You are not listening to your compiler, crank up the warning level.
Now, the problem (or maybe just one?) is actually this:
pthread_create(&pth,NULL,threadFunc(newsockfd),(void*) &i);
This will call threadFunc(newsockfd) and pass the result to pthread_create. The second part will never happen though, because that function calls pthread_exit or falls off the end without returning anything, which could cause anything to happen.
Your server code isn't displaying the printf statements reliably is because you didn't end the strings passed to printf with a "\n".
Change all of your printf statements to include a trailing \n such that output will be "flushed" immediately. E.g.
Instead of:
printf("after pthread create");
Do this:
printf("after pthread create\n");
Repeat that fix for all of your printf statements. And then the program flow will be more readily visible as clients connect to it.
There's probably about 5 or 6 other bugs in your code. The main one that I want to call out is just because the client sent 4 bytes of "EXIT", doesn't mean the TCP stream won't fragment that into "EX" and "IT" across two seperate read calls depending on the state of the intertubes. Always write your protocol code as if read/recv were only going to return one char at a time. OR just use MSG_WAITALL with recv() so that you always read the chunk size.

Client socket won't open using socket() function in a chat client

So this is a work in progress right now, but when I run the commands:
./server 4444
and from a different terminal window, ./client localhost 4444
The client stops at the "Error opening socket."
I have no idea why, and any advice will be greatly appreciated. I am fully aware this code is buggy and incomplete, but I cannot move forward without first getting my client and server to connect properly.
Here is my code:
client.c
#include "../lib/sockettalk.h"
#include "../lib/my.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
//#define MAX_SIZE=255
int main(int argc, char **argv)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);//only need one socket since you are the only one connecting
int n;
char buffer[MAX_SIZE];
struct sockaddr_in serv_addr;
struct hostent *server;
int portnum = atoi(argv[2]);
if(argc < 3)
{
printf("Check your arguments.");
exit(0);
}
//printf("%d", portnum);
if(portnum < 2000 || portnum > 65535)//must be greater than 5000 to avoid conflictin ports
{
printf("Error, port number is out of bounds. Must be >2000 AND <65535.");
printf("Please enter a valid port number next time.");
exit(0);
}
if(sockfd < 0);
printf("Error opening socket. \n");
else
printf("Opened socket directly. \n");
if((server = gethostbyname(argv[1])) == 0)
{
printf("Error, no host. \n");
exit(0);
}
//memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htonl(portnum);
if((connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) < 0)
{
printf("Error connecting. \n");
}
while(1)
{
//clear and write a message
memset(buffer, '0', sizeof(buffer));
if((n = write(sockfd, buffer, my_strlen(buffer))) < 0)
{
printf("Error writing to server. \n");
exit(1);
}
printf("Client: ");
printf("%s", buffer);
printf(" \n");
//clear and read
memset(buffer, '0', sizeof(buffer));
if((n = read(sockfd, buffer, MAX_SIZE)) < 0)
{
printf("Error reading from server. \n");
exit(1);
}
printf("Server: ");
printf("%s", buffer);
printf(" \n");
}
return 0;
}
server.c
#include "../lib/my.h"
#include "../lib/sockettalk.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int port = atoi(argv[1]);
int pid;
int n; //to read and write
char buffer[MAX_BUFFER_SIZE];
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
int newsockfd;
int clilen; //to be used in accept step as a dummy, need size of bytes
struct sockaddr_in cli_addr, serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
if (sockfd<0)
printf("Problem openning socket.\n");
else
{
printf("Openned socket successfully.\n");
}
serv_addr.sin_family = AF_INET; //address family
serv_addr.sin_port = port; //IP port
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP address, INADDR_ANY allows program to work without knowing the IP address of machine it is running on.
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)//assigns a name to a socket. we must also cast serv_addr to a pointer to a struct socketDDR
{
printf("Error binding socket. \n");
exit(1);
}
else
{
printf("Bound socket successfully. \n");
}
if(listen(sockfd, 5) < 0) //should be an already bound socket. 5 is the number of clients that can connect at once
{
printf("Error listning.\n");
exit(1);
}
while(1) //place into loop so that process can repeat for every new connection
{
//now a newsockfd needs to be created so that it gives every new client a unique identifir
newsockfd = accept(sockfd,(struct sockaddr*) &cli_addr, &clilen);
if(newsockfd < 0)
{
printf("Error accepting\n");
exit(1);
}
else
{
printf("Client is connected.\n");
}
if ((pid = fork()) < 0) //problem
{
printf("Error forking. \n");
exit(1);
}
else if(pid == 0) //forking is sucessful, is a child
{
close(sockfd); //closes from the child side
while(1)
{
memset(buffer, 0, sizeof(buffer));
n = read(newsockfd, buffer, MAX_BUFFER_SIZE);
if (n < 0)
{
printf("Error reading from client.\n");
exit(1);
}
printf("%s", buffer);
printf("\n");
memset(buffer, 0, sizeof(buffer));
fgets(buffer, 254, stdin);
n = write(newsockfd, buffer, strlen(buffer));
if(n < 0)
{
printf("Error writing to client.\n");
exit(1);
}
printf("Server: ");
printf("%s", buffer);
printf("\n");
}
close(sockfd);
}
}
return 0;
}
In the client, you aren't actually using the result of server = gethostbyname(...) anywhere. Indeed, you're leaving serv_addr.sin_addr uninitialized, so you're trying to connect to some random IP address (probably 0.0.0.0), which is of course failing.

Client server Process execution by socket programming in c

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,choice;
struct sockaddr_in serv_addr;
struct hostent *server;
int buffer;
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);
}
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("Please enter positive integer ");
printf("Enter your choice\n1=Prime number\n2=Fibonacci number\n 3=power of 2\n");
scanf("%d",&choice);
if(choice==1){
printf("Please enter positive integer ");
scanf("%d", &buffer);
}
n = write(sockfd,&buffer,sizeof(buffer));
if (n < 0)
error("ERROR writing to socket");
char msg[256];
bzero(msg, 256);
n=read(sockfd, msg, 255);
printf("%d %s\n",buffer, msg);
close(sockfd);
return 0;
}
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 prime(int num)
{
int c;
for ( c = 2 ; c <= num - 1 ; c++ )
{
if ( num%c == 0 )
{
return 0;
}
}
if ( c == num )
return 1;
return 0;
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
int buffer;
struct sockaddr_in serv_addr, cli_addr;
int n;
int i=1;
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");
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");
n = read(newsockfd,&buffer,sizeof(buffer));
int result= prime(buffer);
if (n < 0) error("ERROR reading from socket");
printf("Client's input is: %d\n",buffer);
if(result==1)
{
n = write(newsockfd,"is Prime Number",18);
if (n < 0) error("ERROR writing to socket");
}
else
{
n = write(newsockfd,"is not Prime Number",18);
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
close(sockfd);
return 0;
}
In this client-server process, server program is terminated after first execution. I want to:
Server will run infinitely
If I keep client program in more than one pc, each client will be able to communicate and server program will not be terminated.
You'd obviously need to loop and fork then.
An infinite loop around the accept/read/write/close would keep your server running.
As for concurrently accepting multiple connections, you have the choice of creating a new process or thread after accept. Another is making the sockets non-blocking (Google is your friend!) and using polling functions like select or poll.
See my implementation of this task:
https://github.com/H2CO3/TCPHelper
The basic trick is that you'll need to close your accept() into an infinite loop, and fork() or create a new thread after ever accepted conection.
if you don't want to use my helper functions, you'll see some pretty good tutorials here:
http://www.linuxhowtos.org/C_C++/socket.htm
on server side
while (1){
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
if (newsockfd < 0)
error("ERROR on accept");
n = read(newsockfd,&buffer,sizeof(buffer));
int result= prime(buffer);
if (n < 0) error("ERROR reading from socket");
printf("Client's input is: %d\n",buffer);
if(result==1)
{
n = write(newsockfd,"is Prime Number",18);
if (n < 0) error("ERROR writing to socket");
}
else
{
n = write(newsockfd,"is not Prime Number",18);
if (n < 0) error("ERROR writing to socket");
}
}
on client side :
//printf("Please enter positive integer ");
while (choice != -1){
printf("Enter your choice\n1=Prime number\n2=Fibonacci number\n 3=power of 2\n");
fflush(stdin);
scanf("%d",&choice);
if(choice==1){
printf("Please enter positive integer ");
scanf("%d", &buffer);
}
n = write(sockfd,&buffer,sizeof(buffer));
if (n < 0)
error("ERROR writing to socket");
char msg[256];
bzero(msg, 256);
n=read(sockfd, msg, 255);
printf("%d %s\n",buffer, msg);
}// end of while (choice != -1){
On the server side, you need create a process and maybe you can implement a process synchronization system. Critical section, locking resources etc.

Resources