So, I am working on an remote ls assignment in which we have to use TCP socket connection between two remote computers and run client.c on one side and server.c on another. Client program enters command; for e.g: ls
the server will parse it and returns the current working directory to client.
Note that I am running both programs on VM Workstation. One side is Ubuntu and another is Red Hat 6.
Issue: My client program couldn't connect to the server and its connect() function is returning -1.
I have tried to debug my program and so I am attaching the results:debug result
Note: I have hardcoded IP address and port no for the sake of debugging.
Here are the codes:
Client side:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<netdb.h>
#include <string.h>
#include<unistd.h>
/*
Client side socket flow
socket()
|
|
v
connect()
|
|
v
recv()
*/
int main(int argc, char *argv[]) {
struct hostent *server;
struct sockaddr_in server_address;
int port_num;
int communication_status;
//create a socket
int network_socket;
//We will use 3 args while running client code.
/*
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
}*/
/*
socket(arg1,arg2,arg3)
- First arg: (AF_INET) = domain .. from IPV4 domain
- Sec arg: SOCK_STREAM - TCP Stream/Connection-Oriented
- Third arg: defines protocol - 0 for TCP <You can use RAW SOCKET HERE (SOCKETS WITH NO PROTOCOL)
*/
network_socket = socket(AF_INET,SOCK_STREAM,0);
/*
- So we can pass port no as int
- But data format is different from structure that we need to use a conversion function
- conversion function thats going to put our integer
port in right byte order is htons(agr = actual int port number we want to connect to)
*/
//define port you need to conenct remotely
port_num = 20102;
server_address.sin_port = htons(port_num);
//define server address
/*
-sin addr is field that contains structure itself
- we can use any address -- use shortcut ip.0.0.0 (INADDR_ANY)
*
/*
-now we need to use connect() to connect to other socket
- BUT FIRST WE NEED TO SPECIFY AN ADDRESS FOR SOCKET i.e. addr and port no
*/
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("192.168.177.128");
//now time to connect
/*
connect()
arg1: socket
arg2: need to cast our server addfress structure to slightly different struct
from sockaddr_in to sockaddr*
arg3: sizeof the address
connect() returns integer
0 - successful connection
-1 - not successfull
*/
int connection_status;
connection_status = connect(network_socket,(struct sockaddr *) &server_address,sizeof(server_address));
//check for error with the connection
if (connection_status == -1) {
printf("There was an error making a connection to the remote socket \n\n");
}
// recieve data from the server
/*
- recv() function
- first arg: socket
- 2nd arg: address of var where data recived will end up (here it is char array)
- 3rd arg: optional flag parameter give 0
*/
//string to hold data exchanged between client and server
char buffer[256];
printf("Please enter the linux command: ");
//clears the buffer content
bzero(buffer,256);
//get linux command from the console
fgets(buffer,255,stdin);
communication_status = write(network_socket,buffer,strlen(buffer));
//check for write status
if (communication_status < 0) {
perror("Error writing to socket!");
exit(1);
}
//Now getting server response
//clear the buffer
bzero(buffer,256);
communication_status = read(network_socket,buffer,255);
if (communication_status < 0) {
perror("Error reading from socket!");
exit(1);
}
//now we have to print the server response
printf("Server>>: %s\n", buffer);
//close the socket
close(network_socket);
return 0;
}
Server side:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include <stdlib.h>
#include <string.h>
#include<unistd.h>
int readAndParseCmdLine(char **, char **);
int main(int argc, char *argv[]) {
//Checks if the num of argument is 2, if not error message is displayed.
if(argc<2) {
fprintf(stderr,"Num of argument Error");
}
//buffer for data exchange
char buffer[256];
int clientlength, portnum, newSocket;
struct sockaddr_in server_address, cli_addr;
int communication_status,newsockfd;
//create server
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM,0);
if(server_socket == -1) {
perror("Could not connect to socket");
exit(1);
}
//define the server address
bzero((char *) &server_address, sizeof(server_address));
//Coverts the character value to integer for the portno
portnum = atoi(argv[1]);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(portnum);
server_address.sin_addr.s_addr = INADDR_ANY;
//bind the socket to our specified IP and port
//bind is used exactly like we call the connection()
//OS gives resources like port number to Server through bind()
if ( bind(server_socket,(struct sockaddr*) &server_address,sizeof(server_address)) < 0 ) {
perror("Can't bind");
exit(1);
}
/*
listen()
first arg: socket
second arg: backlog (how many connection can be waiting -
essentially for this particular socket at a time - since
we are using this for one client, we can use any number)
*/
listen(server_socket,5);
clientlength = sizeof(cli_addr);
/*
define integer to hold client's socket as once we able to listen() connection
and we can actually start accepting() connections so we can read or write to
clients socket
*/
//The new socket for the client informations
/*
if(newsockfd<1)
{
sleep(1);
}
*/
newSocket = accept(server_socket,(struct sockaddr *) &cli_addr, &clientlength);
if (newSocket < 0) {
perror("ERROR on accept");
exit(1);
}
//Clears the buffer
bzero(buffer,256);
communication_status = read(newSocket,buffer,255);
if (communication_status < 0) {
perror("ERROR reading from socket");
exit(1);
}
//Buffer Stores the msg sent by the client
printf("Here is the entered bash command: %s\n",buffer);
communication_status = write(newSocket,"I got your message",18);
if (communication_status < 0)
{
error("ERROR writing to socket");
}
char *prog;
strcpy(prog, buffer);
char *args[100];
int child_pid;
//Running the Bash Commands
if(readAndParseCmdLine(&prog, args)) {
child_pid =fork();
if(child_pid == 0){ //child part
printf("\n");
execvp(prog, args); // create and run the new process and close the child process
printf("\n");
prog = NULL;
printf("Error in excuting the command- please make sure you type the right syntax.\n");
} else{ //parent part
wait(child_pid);
}
void main();
}
}
//This function reads the linux command form the buffer and parse it
//
int readAndParseCmdLine(char **prog, char **args){
int i =0;
char cmd[100]; //user command
char * temp;
temp = *prog;
if(strcmp(temp,"exit")==0){return 0;} //end program if user type exit.
char *tok;
tok = strtok(temp," \n");
while(tok != NULL){
if(i==0){
prog[0] = tok;
}
args[i] = tok;
printf("\n");
i=i+1;
tok = strtok(NULL, " \n");
}
args[i]=NULL;
return 1;
}
Related
Both programs compile, and I'm able to successfully create a socket, but the connection to the server fails. This is basically a TCP echo program.
PS. I'm new here so IDK how to use this, I don't have much programming experience so bare with me.
tcp echo client-1
tcp echo client-2
tcp echo server-1
tcp echo server-2
Compiling/Running server gives me: Server not fully implemented...
Compiling/Running client gives me: Socket successfully created..Error: connection to the server failed!
**// TCP echo client program**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main (int argc, char* argv[ ]) // Three arguments to be checked later
{
struct sockaddr_in servAddr; // Server socket address data structure
char *servIP = argv[1]; // Server IP address from command line
int servPort = atoi(argv[2]); // Server port number from command line
char *message = argv[3]; // Message specified on the command line
char buffer [512 + 1];
char* ptr = buffer;
int len;
int max_len = sizeof(buffer);
int sock_descrip;
// Check for correct number of command line arguments
if(argc != 4) {
printf("tcp-echo-client [IP address] [Port] [Message]\n");
exit (1);
}
// Populate socket address for the server
memset (&servAddr, 0, sizeof(servAddr)); // Initialize data structure
servAddr.sin_family = AF_INET; // This is an IPv4 address
servAddr.sin_addr.s_addr = inet_addr(servIP); // Server IP address
servAddr.sin_port = servPort; // Server port number
// Create a TCP socket stream
int sock;
if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
printf("Error: socket creation failed!\n");
exit (1);
}
else
printf("Socket successfully created..\n");
// Connect to the server
if ((connect (sock, (struct sockaddr*)&servAddr, sizeof(servAddr))) == -1) {
printf("Error: connection to the server failed!\n");
exit (1);
}
else
printf("Connected to the server..\n");
// Send data to the server...
send(sock_descrip, message, strlen(message),0);
int x;
while ((x = recv(sock_descrip, ptr, max_len,0))>0)
{
ptr += x;
max_len -= x;
len += x;
}
buffer[len] = '\0';
printf("Echoed string received: %s %c", buffer,*message);
// Receive data back from the server..
// Loop while receiving data...
// print data...
// end-while loop
// Close socket
close (sock);
// Stop program
exit (0);
} // End main
**//TCP Echo server program**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFLEN 512 // Maximum length of buffer
#define PORT 9988 // Fixed server port number
int main (void)
{
struct sockaddr_in server_address; // Data structure for server address
struct sockaddr_in client_address; // Data structure for client address
int client_address_len = 0;
char buffer [512];
char* ptr = buffer;
int len;
int max_len = BUFLEN;
int sock_descrip;
// Populate socket address for the server
memset (&server_address, 0, sizeof (server_address)); // Initialize server address data structure
server_address.sin_family = AF_INET; // Populate family field - IPV4 protocol
server_address.sin_port = PORT; // Set port number
server_address.sin_addr.s_addr = INADDR_ANY; // Set IP address to IPv4 value for loacalhost
// Create a TCP socket; returns -1 on failure
int listen_sock;
if ((listen_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
printf("Error: Listen socket failed!\n");
exit (1);
}
// Bind the socket to the server address; returns -1 on failure
if ((bind(listen_sock, (struct sockaddr *)&server_address, sizeof (server_address))) == -1) {
printf("Error: binding failed!\n");
exit (1);
}
printf("Server not fully implemented...\n");
// Listen for connections...
int wait_size;
if (listen(listen_sock, wait_size) == -1)
{
printf("Error: listening failed!\n");
exit(1);
}
for(;;)
{
if(sock_descrip=accept(listen_sock,(struct sockaddr *)&client_address, &client_address_len) == -1)
{
printf("Error: accepting failed!\n");
exit(1);
}
int x;
while ((x = recv(sock_descrip, ptr, max_len, 0)) > 0)
{
ptr += x;
max_len -= x;
len += x;
}
send(sock_descrip,buffer,len,0);
}
// Echo data back to the client...
close (listen_sock); // Close descriptor referencing server socket
} // End main
You need parentheses around the assignment:
if(
(sock_descrip=accept(listen_sock,(struct sockaddr *)&client_address, &client_address_len))
== -1)
I have a simple server and client written in C.
They communicate well until the very end of my program where the server seems to skip the "read" method and just proceeds, it'll print out a blank line at
printf("%s", playAgain);
Here is the end of the 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 <netdb.h>
#include <arpa/inet.h>
#define BACKLOG 10
char invalidPortNumber[] = "Please specify a port number between 2000 and 65535";
char intro[] = "Welcome to the prisoners dilemma";
char playGame[] = "Will you stay silent or betray the other prisoner?\nType S for silent or B for betray";
char option1[] = "The other prisoner betrayed you\nYou each get 2 years in prison";
char option2[] = "The other prisioner betrayed you\nYou get 3 years in prison, the other prisioner is set free";
char option3[] = "The other prisioner stayed silent\nYou are set free, the other prisioner gets 3 years in prison";
char option4[] = "The other prisioner stayed silent\nYou both get 1 year on a lesser charge";
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Run with port number as the argument\n");
exit(1);
}
int port = atoi(argv[1]);
if (port<2000 || port>65535){
printf("%s\n", invalidPortNumber);
exit(2);
}
//Struct to store information for IPv4 address
struct sockaddr_in serverAddress;
//Create socket for IPv4, reliable stream (TCP), default protocol
int serverSocket = socket(PF_INET, SOCK_STREAM, 0);
//Specify that IPv4 family addresses will be used
serverAddress.sin_family = AF_INET;
//Set the port number
serverAddress.sin_port = htons(port);
//Bind to all local interfaces for IP
serverAddress.sin_addr.s_addr = INADDR_ANY;
//Bind the created socket to the IP address specified in the sockaddr_in struct
bind(serverSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress));
//Listen for connections, allowing backlog of up to BACKLOG connection requests
listen(serverSocket, BACKLOG);
int play = 0;
while(1) {
//Struct to store info of connecting clients
struct sockaddr_in clientAddress;
socklen_t clientAddrSize = sizeof(clientAddress);
//Create a socket for the connection between the client and server
int connectionSocket = accept(serverSocket, (struct sockaddr *) &clientAddress, &clientAddrSize);
//Input buffer to store client's request
do{
char input[800];
memset(input, '\0', sizeof(input));
//Have intro to the game
write(connectionSocket, intro, sizeof(intro) - 1);
//Read client's input
read(connectionSocket, input, sizeof(input)-1);
if(strcmp(input,"Y\n")==0||strcmp(input,"y\n")==0){
write(connectionSocket, playGame, sizeof(playGame) - 1);
}
else if(strcmp(input,"N\n")==0||strcmp(input,"n\n")==0){
write(connectionSocket, "Okay, connection closed", sizeof("Okay, connection closed") - 1);
close(connectionSocket);
return 0;
}
//read clients choice
char clientChoice[2];
read(connectionSocket, clientChoice, sizeof(clientChoice)-1);
srand(time(NULL));
int random = rand();
if( random % 2 ==0 ){
char serverChoice[2] = "S";
if(strcmp(clientChoice, "S")==0){
write(connectionSocket, option4, sizeof(option4) - 1);
}
else if(strcmp(clientChoice, "B")==0){
write(connectionSocket, option3, sizeof(option3) - 1);
}
}
else {
char serverChoice[2] = "B";
if(strcmp(clientChoice, "S")==0){
write(connectionSocket, option2, sizeof(option2) - 1);
}
else if(strcmp(clientChoice, "B")==0){
write(connectionSocket, option1, sizeof(option1) - 1);
}
}
char playAgain[5];
read(connectionSocket, playAgain, sizeof(playAgain)-1);
printf("%s",playAgain);
if(strcmp(playAgain, "Play")==0){
printf("Playing again");
play=1;
}
}while(play==1);
}
//Close the server socket and terminate the program if the loop ever ends
close(serverSocket);
return 0;
}
That is the server.
And now here is the end of the Client
#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 <netdb.h>
#include <arpa/inet.h>
#define BACKLOG 10
char invalidPortNumber[] = "Please specify a port number between 2000 and 65535";
char intro[] = "Welcome to the prisoners dilemma";
int main(int argc, char *argv[]) {
char buffer[512];
char IPAddress[15];
int n;
if (argc < 2) {
printf("Run with host IP and port number as the argument\n");
exit(1);
}
int port = atoi(argv[1]);
if (port<2000 || port>65535){
printf("%s\n", invalidPortNumber);
exit(2);
}
//Struct to store information for IPv4 address
struct sockaddr_in serverAddress;
//Create socket for IPv4, reliable stream (TCP), default protocol
int serverSocket = socket(PF_INET, SOCK_STREAM, 0);
//Specify that IPv4 family addresses will be used
serverAddress.sin_family = AF_INET;
//Set the port number
serverAddress.sin_port = htons(port);
//Bind to all local interfaces for IP
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
//Bind the created socket to the IP address specified in the sockaddr_in struct
int play=0;
if(connect(serverSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress))<0){
printf("Couldn't connect, make sure the server is running and port number is correct \n");
return 1;
}
//read intro from server
do{
bzero(buffer,512);
n = read(serverSocket,buffer,511);
printf("%s\n",buffer);
//ask user if they'd like to play
int validCommand=1;
do{
printf("Would you like to play? (Y/N) ");
bzero(buffer,512);
fgets(buffer,511,stdin);
if(strcmp(buffer, "Y\n")==0||strcmp(buffer, "N\n")==0){
validCommand=0;
}
else{
printf("Invalid command \n");
}
}while(validCommand==1);
//write whether user wants to play to server
n = write(serverSocket,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,512);
//read response from server
n = read(serverSocket,buffer,511);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
if(strcmp(buffer, "Okay, connection closed")==0){
close(serverSocket);
return 0;
}
do{
bzero(buffer,512);
printf("Make your choice (B/S) ");
fgets(buffer,511,stdin);
if(strcmp(buffer, "B\n")==0||strcmp(buffer, "S\n")==0){
validCommand=0;
}
else{
printf("Invalid command \n");
validCommand=1;
}
}while(validCommand==1);
//write the users choice to the server
n = write(serverSocket,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,512);
n = read(serverSocket,buffer,511);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
do{
bzero(buffer,512);
printf("Would you like to play again? (Play/Quit) ");
fgets(buffer,511,stdin);
if(strcmp(buffer, "Play\n")==0||strcmp(buffer, "Quit\n")==0){
validCommand=0;
}
else{
printf("Invalid command \n");
validCommand=1;
}
}while(validCommand==1);
//write the users choice to the server
if(strcmp(buffer, "Quit\n")==0){
printf("Closing Connection to server");
close(serverSocket);
return 0;
}
if(strcmp(buffer, "Play\n")==0){
printf("Playing again");
play=1;
n = write(serverSocket,buffer,strlen(buffer)-1);
if (n < 0)
error("ERROR writing to socket");
}
}while(play==1);
}
Both the client and server work for the Choice B/S, the client sends, and the server responds. I have no idea what could be wrong, but the server seems to not wait for the clients final command
First, I think the basic problem you're running into is the common misconception that 1 write corresponds to 1 read automagically. It doesn't.
The problem you mention is caused by your reads and writes being out of sync. You need to make sure that you are reading the same amount as you send each time. The server isn't "proceeding without waiting to read client command;" it has just already read and ignored it.
For instance, when the client does
write(serverSocket, buffer, strlen(buffer))
the server is going to be confused. If you don't send over the size of the string first, the server can't know when to stop reading. This is especially true since you don't send the NUL-terminator. This specific problem could be avoided by doing more processing on the client side. By checking the input against "Y" and "N" on the client, you can simplify the communication to simply sending over a one byte boolean value. This reduces the complexity of your code and the amount of communication required between server and client.
If you would like examples of how you might start improving this, or have questions, just ask in the comments.
Side notes:
1) You don't need to send the intro over the socket; it's already on the client side.
2) Boolean variables like validCommand are conventionally 0 for false and 1 for true. You seem to have this flipped in your code. It's not wrong per se, just confusing to read.
I'm trying make the program run multiple threads to it connects to different ports. I successfully made it work on a single thread but not multiple.
Below I have posted the code of what I'm using on XUbuntu.
server.c
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
// File io storing in lof file
#include "server_portLog.h"
// Thread used to create sockets
#include "sockets_pthread.h"
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
// Server port number
//int portNumber = atoi(argv[1]);
// sockfd: ip-address socket, newsockfd: socket from receiving client, portNum: Which port will be listening, num_bytes: received data from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);
// Getting all ports from command line parameters and creating a socket for each
int numPorts = argc - 1;
struct port varPorts[numPorts];
pthread_t portsSockets[numPorts];
for (int i = 0; i < numPorts; i++) {
varPorts[i].portNumber = atoi(argv[i + 1]);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&portsSockets[i], &attr, createSocket, &varPorts[i]);
}
// Infinite loop too keep listening even after connection to client closes
while (1) {
// After that all the ports entered have a socket of their own the program runs them parallel together to see if any client tries to connect with one of the ports
for (int i = 0; i <= numPorts; i++) {
pthread_join(&portsSockets[i], NULL);
/* Start listening for the clients (thread blocks) */
if (listen(varPorts[i].sockfd, 5) != 0) {
printf("Error: listen() failed for port: %d \n", varPorts[i].portNumber);
//return 3;
}
// Accepting connection from client & creating socket with that client data
newsockfd = accept(varPorts[i].sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
printf("Error: accept() failed for port: %d \n", varPorts[i].portNumber);
//return 4;
}
/* To send receive data */
// Clearing buffer
memset(buffer, 0, BUFFER_SIZE);
// Show data received from client
num_bytes = recv(newsockfd, buffer, BUFFER_SIZE-1, 0);
if (num_bytes < 0) {
printf("Error: recv() failed for port: %d \n", varPorts[i].portNumber);
//return 5;
}
// Checking version of server if LOGFILE it creates a file to store the ports
#if defined LOGFILE
// Checking if user wrote a fileName for the logs or going to use the default log file
if (argc == 3) {
char *textFile = argv[argc-1];
serverLogFile_Custom(buffer, textFile);
}
else {
serverLogFile_Defualt(buffer);
}
#else
// Print the port numbers that connect to server
printf("Received: Client using port- %s to connect \n", buffer);
#endif
// Closing connection with client
close(newsockfd);
}
}
return 0;
}
Sockets_pthreads.h
#include <pthread.h>
struct port {
int portNumber;
int sockfd;
};
void* createSocket(void* portNumber) {
// sockfd: ip-address socket, newsockfd: socket from receiving client, portNum: Which port will be listening, num_bytes: received data from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
//char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);
struct port *portStruct = (struct port*) portNumber;
// Creating a new socket with ip-Protocol_tcp
// Parameters: Internet-domain, socket-stream, TCP-protocol
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
printf("Error: Failed to open socket for port: %d \n", portStruct->portNumber);
//return 1;
}
// Setting all bits in padding-field to 0
memset(&serv_addr, 0, sizeof(serv_addr));
// Initializing socket in sockaddr_in (stucture)
serv_addr.sin_family = AF_INET; // Seting family-Internet
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portStruct->portNumber); // Setting portNum (passed in command line)
// Binding the address-structure to the socket
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("Error: bind() failed for port: %d \n", portStruct->portNumber);
//return 2;
}
// Geting sockfd
portStruct->sockfd = sockfd;
pthread_exit(0);
}
Problem is not clear what needs to be implemented. If various ports sockets have to accept, then it has to happen in thread function as well as recv call. In server function there are accept and recv calls which are blocking by default.
The main function should wait for connections. Upon receiving a request from the client, you create a thread that will handle this specific connection. So you will create the threads in the loop, meaning, you can theoretically have an infinite number of threads.
However, you can add a little logic to limit the number of threads that are existing at a particular time (thread pool).
So your main loop can look like this:
while (1) {
// accept: wait for a connection request
childfd = accept(parentfd, (struct sockaddr *) &clientaddr, (socklen_t *) &clientlen);
if (childfd < 0){
fprintf(stderr,"ERROR on accept");
continue;
}
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL){
fprintf(stderr,"ERROR on inet_ntoa\n");
continue;
}
fprintf(stdout,"server established connection with client\n");
pthread_t new_thread;
newSock = malloc(1);
*newSock = childfd;
if( pthread_create( &new_thread , NULL , server_thread , (void*) newSock) < 0){
bzero(logMsg, MAXSTRING);
sprintf(logMsg, "Thread for connection %d could not be created",childfd);
fprintf(stderr, "%s\n", logMsg);
continue;
}
fprintf(stdout, "thread created for connection %d\n", childfd);
}
The server_thread function could look like:
void *server_thread(void* clientSock){
int childfd = *(int*)clientSock;
char buf[MAXLINE]; // message buffer
int n; // message byte size
char logMsg[MAXSTRING];
size_t siz_failresp;
// read: read input string from the client
bzero(buf, MAXLINE);
n = (int) read(childfd, buf, MAXLINE);
if (n < 0){
sprintf(logMsg, "ERROR reading from socket");
fprintf(stderr,"%s", logMsg);
close(childfd);
fprintf(stdout, "Client %d disconnected \n=================\n", childfd);
//Free the socket pointer
free(clientSock);
return NULL;
}
// else, do processing of data received...
// ...................
}
There may be unused variables here above... I just got this code from one of my projects, just removing parts that do not concern you :-)
Hope it helps
Hi i am programming a networking client in c and i am using the getsocketname function to return the IP and port of the socket i have created but for some reason the IP is always returned as 0.0.0.0 here is the code:
#include <stdio.h> //include standard input/output library
#include <stdlib.h> //include standard libraries
#include <string.h> //include string headers
#include <unistd.h> //add definitions for constansts and functions
#include <sys/types.h> // include definitions for different data types
#include <sys/socket.h> //include socket support
#include <netinet/in.h> //define internet protocol functions
#include <arpa/inet.h> //define internet protocol functions
#include "Practical.h" //include practical header file
int main(int argc, char *argv[]) {
char myIP[16];
unsigned int myPort;
struct sockaddr_in server_addr,myaddr;
if (argc < 3 || argc > 4) // Test for correct number of arguments
DieWithUserMessage("Parameter(s)",
"<Server Address> <Echo Word> [<Server Port>]");
char *servIP = argv[1]; // First arg: server IP address (dotted quad)
char *echoString = argv[2]; // Second arg: string to echo
// Third arg (optional): server port (numeric). 7 is well-known echo port
in_port_t servPort = (argc == 4) ? atoi(argv[3]) : 7; //21
// Create a reliable, stream socket using TCP //23
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//this block of code creates a reliable tcp stream socket and checks what the returned integer is from the socket function, the returned function will give a integer that descibes the socket. if this is 0 then kill the socket and show the user an error message.
if (sock < 0)
DieWithSystemMessage("socket() failed"); //26
// Construct the server address structure //28
struct sockaddr_in servAddr; // Server address
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
// Convert address
int rtnVal = inet_pton(AF_INET, servIP, &servAddr.sin_addr.s_addr);
if (rtnVal == 0)
DieWithUserMessage("inet_pton() failed", "invalid address string");
else if (rtnVal < 0)
DieWithSystemMessage("inet_pton() failed");
servAddr.sin_port = htons(servPort); // Server port
myaddr.sin_addr.s_addr = INADDR_LOOPBACK;
bzero(&myaddr,sizeof(myaddr));
int len = sizeof(myaddr);
getsockname(sock,(struct sockaddr *) &myaddr, &len);
inet_ntop(AF_INET, &myaddr.sin_addr, myIP, sizeof(myIP));
myPort = ntohs(myaddr.sin_port);
printf("local ip address : %s\n", myIP);
printf("local port: %u\n", myPort);
// Establish the connection to the echo server
if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("connect() failed");
size_t echoStringLen = strlen(echoString); // Determine input length //44
// Send the string to the server
ssize_t numBytes = send(sock, echoString, echoStringLen, 0);
if (numBytes < 0) //sending string to server, number of bytes of the message is equal to return value of send function, if the number of bytes is less than 0 then do not send and say to user that the send failed
DieWithSystemMessage("send() failed");
else if (numBytes != echoStringLen)
DieWithUserMessage("send()", "sent unexpected number of bytes"); //51
// if the number of bytes is not equal to the input length of the string parsed as an argument then die with the message to the user saying sent unexpected number of bytes.
// Receive the same string back from the server //53
unsigned int totalBytesRcvd = 0; // Count of total bytes received
fputs("Received: ", stdout); // Setup to print the echoed string
while (totalBytesRcvd < echoStringLen) {
char buffer[BUFSIZE]; // I/O buffer
/* Receive up to the buffer size (minus 1 to leave space for
a null terminator) bytes from the sender */
numBytes = recv(sock, buffer, BUFSIZE - 1, 0);
if (numBytes < 0)
DieWithSystemMessage("recv() failed");
else if (numBytes == 0)
DieWithUserMessage("recv()", "connection closed prematurely");
totalBytesRcvd += numBytes; // Keep tally of total bytes
buffer[numBytes] = '\0'; // Terminate the string!
fputs(buffer, stdout); // Print the echo buffer
}
fputc('\n', stdout); // Print a final linefeed //70
close(sock);
exit(0);
}
//closing off connections to clean up data left over.
the port number returned is always 0 too, i am assigning the address of the myaddr struct to be loopback address so i believe it is supposed to return 127.0.0.1 as the IP but it isn't, i am sort of new to socket programming so my logic might not be perfect, i just cant see whats wrong here
It means that the socket hasn't been bound to a local address yet.
You need to get the local address after it has been bound, which happens automatically with the connect call.
I complile the following C code of UDP client
after I run './udpclient localhost 9191' in terminal.I put "Enter Text= " as Hello, but it is showing error in sendto as below:
Enter text: hello
hello
: error in sendto()guest-1SDRJ2#md-K42F:~/Desktop$
"
Note: I open 1st the server port as below in other terminal
./server 9191.
I beleive there is no error in server code. The udp client is not passing message to server. If I don't use thread , the message is passing .But I have to do it by thread.
UDP client Code:
/* simple UDP echo client */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <pthread.h>
#define STRLEN 1024
static void *readdata(void *);
static void *writedata(void *);
int sockfd, n, slen;
struct sockaddr_in servaddr;
char sendline[STRLEN], recvline[STRLEN];
int main(int argc, char *argv[]) {
pthread_t readid,writeid;
struct sockaddr_in servaddr;
struct hostent *h;
if(argc != 3) {
printf("Usage: %s <proxy server ip> <port>\n", argv[0]);
exit(0);
}
/* create hostent structure from user entered host name*/
if ( (h = gethostbyname(argv[1])) == NULL) {
printf("\n%s: error in gethostbyname()", argv[0]);
exit(0);
}
/* create server address structure */
bzero(&servaddr, sizeof(servaddr)); /* initialize it */
servaddr.sin_family = AF_INET;
memcpy((char *) &servaddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
servaddr.sin_port = htons(atoi(argv[2])); /* get the port number from argv[2]*/
/* create a UDP socket: SOCK_DGRAM */
if ( (sockfd = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
printf("\n%s: error in socket()", argv[0]);
exit(0);
}
pthread_create(&readid,NULL,&readdata,NULL);
pthread_create(&writeid,NULL,&writedata,NULL);
while(1)
{
};
close(sockfd);
}
static void * writedata(void *arg)
{
/* get user input */
printf("\nEnter text: ");
do {
if (fgets(sendline, STRLEN, stdin) == NULL) {
printf("\n%s: error in fgets()");
exit(0);
}
/* send a text */
if (sendto(sockfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
printf("\n%s: error in sendto()");
exit(0);
}
}while(1);
}
static void * readdata(void *arg)
{
/* wait for echo */
slen = sizeof(servaddr);
if ( (n = recvfrom(sockfd, recvline, STRLEN, 0, (struct sockaddr *) &servaddr, &slen)) < 0) {
printf("\n%s: error in recvfrom()");
exit(0);
}
/* null terminate the string */
recvline[n] = 0;
fputs(recvline, stdout);
}
The problem is that you're using the same sockaddr struct (servaddr) for both the sendto and revfrom calls. The recvfrom happens first, so it clears out servaddr in preparation for writing in the source address of the received packed (once it receives one -- that thread is still blocked in the kernel waiting for a packet). Then, when the sendto call occurs, the sockaddr is all zeros, so it immediately returns EINVAL.
You may be getting confused by the fact that the sockaddr argument to recvfrom is an OUTPUT, not an input -- it gets filled in with the source address of the packet that is received (which could be from anywhere). If you want to only receive packets from a particular place (the server?), you need to check the address after the recvfrom returns and toss the packet if it comes from somewhere else, looping back to recvfrom again.