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

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.

Related

TCP Client-Server "bad address" error (in C)

Although it seems to be correctly implemented, it keeps on returning me ERROR when I establish a connection using the loopback address(127.0.0.1).
In addition to a simple TCP Client/Server connection, I have added an additional case:
If the client tries to send data but finds the connection closed, it is closed too. I perform it by checking if received data is equal to 0 (recv).
Given error:
CLIENT:
Welcome to the Client mode
Please, enter the Server's IP Address and Port (eg. 192.128.192.0 1320)
127.0.0.1 2700
Connected to the server. Now you can send messages
Please, enter a message. Enter "FINISH" if you want to finish the connection
ECHO
client: connection closed ->: Success
(1 bytes)Closing the connection
SERVER:
Hello and welcome to the Server mode
Please, enter the Server's Port (eg. 1320)
2700
Server socket successfully configured
Server listening [Clients allowed: 5]
server: accept error: Bad address
Client implementation:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
/**
struct sockaddr{
uint8_t sa_len; // struct length
sa_family_t sa_family; //protocol family: AF_XXX
char sa_data[8]; //socket addr
}
*/
//void notConnected();
int main(){
struct sockaddr_in serv_addr; //port + ip_addr
int my_socket, tcp_port;
char serv_host_addr[30];
char buffer[1024], inbuff[1024];
int io_buffer;
printf("Welcome to the Client mode\n");
//CONFIGURING THE CONNECTION
my_socket = socket(AF_INET, SOCK_STREAM, 0);//(2)
if(my_socket < 0){
perror("client: socket() error ->");
exit(EXIT_FAILURE);
}
bzero(&serv_addr, sizeof(serv_addr));//(4)
printf("Please, enter the Server's IP Address and Port (eg. 192.128.192.0 1320) \n");
scanf("%s %d", serv_host_addr, &tcp_port);//(1)
serv_addr.sin_family = AF_INET ;
serv_addr.sin_port = htons(tcp_port);
if(inet_pton(AF_INET,serv_host_addr,&serv_addr.sin_addr) < 1){
perror("client: inet_pton() error ->");
exit(EXIT_FAILURE);
}
if((connect(my_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr) )) < 0)//(5)
{
perror("client: connect() error ->");
exit(EXIT_FAILURE);
}
//ONCE CONNECTED, START THE SENDING/RECEIVING
printf("Connected to the server. Now you can send messages\n");
bzero(&buffer, sizeof(buffer));
while(strcmp(buffer, "OK\n") != 0){
printf("Please, enter a message. Enter \"FINISH\" if you want to finish the connection\n");//(3)
bzero(&buffer, sizeof(buffer));
fgets(buffer, sizeof(buffer), stdin);
io_buffer = send(my_socket, buffer, strlen(buffer),0);//(6)
if(io_buffer < 0){
perror("client: send() error ->");
exit(EXIT_FAILURE);
}
printf("ECHO %s (%d bytes)", buffer, io_buffer);
//RECEIVE AND CHECK IF CONNECTION HAS BEEN CLOSED
io_buffer = recv(my_socket, buffer, sizeof(buffer),0);
if(io_buffer < 0){
perror("client: recv() error ->");
exit(EXIT_FAILURE);
}
else if(io_buffer == 0){ //THIS IS SERVER IS CLOSED
perror("client: connection closed ->");
break;
}
printf("ECHO %s (%d bytes)", buffer, io_buffer);
}
printf("Closing the connection \n");
for(int i=0; i < 5; i++){
printf(". ");
usleep(500000);
}
close(my_socket);
}
Server implementation:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LISTENQ 5
int main()
{
struct sockaddr_in cli_addr, serv_addr;
char buffer[1024];
int serv_socket, cli_socket, clilen, io_buffer;
int tcp_port;
printf("Hello and welcome to the Server mode\n");
// ASKING FOR PORT NUMBER
if((serv_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("server: can't open stream socket");
exit(EXIT_FAILURE);
}
printf("Please, enter the Server's Port (eg. 1320) \n");
scanf("%d", &tcp_port);
// CONFIGURING THE CONNECTION
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(tcp_port);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// ASSIGNING A NAME TO THE SOCKET
if(bind(serv_socket,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
perror("server: can't assign a name to the socket");
exit(EXIT_FAILURE);
}
printf("Server socket successfully configured\n");
printf("Server listening [Clients allowed: %d]\n", LISTENQ);
if(listen(serv_socket, LISTENQ) < 0)
{
perror("server: fail to listen network");
exit(EXIT_FAILURE);
}
// READ & WRITE STREAM
while(1){
//returns a file descriptor for the client
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,(socklen_t *) sizeof(cli_addr));
if(cli_socket < 0){
perror("server: accept error");
exit(EXIT_FAILURE);
}
printf("Server successfully connected to Client\n");
while(1)
{
if ((io_buffer=recv(cli_socket,buffer,sizeof(buffer),0))<0){
perror("ERROR: recv");
exit(EXIT_FAILURE);
}
printf("\"%s\" received from client", buffer);
if(strcmp(buffer, "FINISH") == 0)
{
break;
}
if ((io_buffer=send(cli_socket,buffer,strlen(buffer),0))!=strlen(buffer)){
perror("ERROR: send");
exit(EXIT_FAILURE);
}
bzero(buffer, sizeof(buffer));
}
strcpy(buffer, "OK");
if ((io_buffer=send(cli_socket, buffer, strlen(buffer), 0)) != strlen(buffer)){
perror("ERROR: send");
exit(EXIT_FAILURE);
}
printf("\"OK\" message sent to the Client.\n");
printf("Closing the connection \n");
for(int i=0; i < 5; i++)
{
printf(". ");
usleep(500000);
}
close(cli_socket);
}
}
In your original question, your accept call looks like this:
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,
(socklen_t *) sizeof(cli_addr));
This passes "(socklen_t *) sizeof(cli_addr)" as the third parameter to accept. This is expected to be a pointer to the size of the structure. You should be passing in a pointer to a socklen_t containing the size of the structure passed as parameter two. The size you're currently passing in is being interpreted as an address, which is then causing your program to crash when it is referenced. The code should look like this:
socklen_t cli_addr_size = sizeof(cli_addr);
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,
&cli_addr_size);

C multisocket program not working

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.

Sockets TCP 2-way connection

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.

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 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