I'm working on a simple client/server implementation in which the client connects to the server based on the command line argument that specifies the hostname to search for a socket to connect with on (I just input localhost) and then sends a singular string that is reversed by the server, and then this reversed string is sent back to the client, and the reversed string prints. I am able to connect to the socket that lives at localhost (the client) but writing through the socket fails, and I am not sure why.
This is the server code: It has a built in reverser function that manually reverses a string and then writes it back through the socket to the client after reading in the original message that was written to the server by the client
#include <netdb.h>
#define BACKLOG 20
#include "server.h"
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_MESSAGE_LENGTH 200
char* reverse(char * word){
char *reversed;
int m=strlen(word);
reversed=(char*)(malloc(sizeof(char) * m));
printf("%d",m);
int i=0;
while (i++!=m){
char d= *(word+m-i);
strncat(reversed,&d,1);
}
return reversed;
}
void reverser_response(int sockfd,char *write_buff,char *read_buff){
read(sockfd,read_buff,sizeof(read_buff));
char *reversed_message=reverse(read_buff);
int i=0;
while (*(reversed_message)!='\0'){
write_buff[i]=*(reversed_message);
i++;
reversed_message=reversed_message+i;
}
write(sockfd,write_buff,sizeof(write_buff));
bzero(write_buff,sizeof(write_buff));
bzero(read_buff,sizeof(read_buff));
}
int main(){
int cfd,afd;
//I'm pretty sure service will be the port name
char service[NI_MAXSERV];
//hostname will be the name of the IP address
char host[NI_MAXHOST];
char read_buff[200];
char write_buff[200];
//I rmemember hints is used to set certain settings within the struct addrinfo result we create
struct addrinfo hints;
//this is used for looping through possible addrinfo structus
struct addrinfo *result, *rp;
//I think this stores the address of the client that connect with us
struct sockaddr_storage claddr;
//combined host + service name with padding of 10 bits
char addrstr[NI_MAXHOST+NI_MAXSERV+10];
memset(&hints,0,sizeof(struct addrinfo));
//socklen is the size of the socket
socklen_t socklen;
//I think AF_UNSPEC means that we can use an unspecified IP protocl: IPV4 or IPV6
hints.ai_family=AF_UNSPEC;
//stream socket
hints.ai_socktype=SOCK_STREAM;
hints.ai_next=NULL;
hints.ai_canonname=NULL;
hints.ai_addr=NULL;
//Passive: we wait for someone to join with our socket, numeric serv: use the numeric host name
hints.ai_flags=AI_PASSIVE | AI_NUMERICSERV;
//getadrrinfo: 0 is success, takes in as arguments, NULL(?) our port number, references to the hints and result addrinfo structs
//actually getaddrinfo generates a linked list of addrinfo structs for the specified host name/service name
//in this case, result is the head of the linkedlist, hints is the hints thing that sets csome conditions
if ((getaddrinfo(NULL,PORT_NUM,&hints,&result))!=0){
printf("Failed to get result pointer of address structs");
exit(EXIT_FAILURE);
}
//loop through possible addrinfo structs we can successfully create a socket at. Create socket at every possible struct. If we are successful
//in binding then quit. bind takes as arguments the socket's file descriptor, the address of the socket, and the lenth of the socket's address
//socket takes as arguments the addrinfo structu's ai_family (IPV4/6), socketpye (stream socket), and the protocol?
for (rp=result;rp;rp!=NULL){
cfd=socket(rp->ai_family,rp->ai_socktype, rp->ai_protocol);
if (cfd==-1){
continue;
}
//rp->ai_addr could be a pointer to a sockaddr_in or sockaddr_in6
if (bind(cfd,rp->ai_addr, rp->ai_addrlen)==0){
break;
}
}
if (rp==NULL){
printf("Reached end of address list without finding suitable socket address space");
exit(EXIT_FAILURE);
}
freeaddrinfo(result);
if (listen(cfd,BACKLOG)==0){
printf("Server listening....\n");
}
for (;;){
socklen=sizeof(struct sockaddr);
afd=accept(cfd,(struct sockaddr*) &claddr,&socklen);
if (afd==-1){
perror("Accept failed");
}
getnameinfo((struct sockaddr*) &claddr,socklen,
host,NI_MAXHOST,service,NI_MAXSERV,0);
snprintf(addrstr,NI_MAXSERV+NI_MAXHOST+10, "Connection received from: (%s, %s)", host,service);
printf("%s\n",addrstr);
reverser_response(afd,write_buff,read_buff);
}
close(afd);
close(cfd);
}
And this is the server implementation, which sends a message to the server, and then reads through the socket the reversed message the server sends back:
#include <netdb.h>
#include "server.h"
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "struct.h"
#define MAX_MESSAGE_LENGTH 200
void chat_function(int sockfd,char *write_buffer,char *read_buffer){
printf("\nEnter a message to send to the server. The server will reverse it, and send it back\n");
fscanf(stdin,"%s",write_buffer);
int m=strlen(write_buffer);
write_buffer[m]='\0';
int i=0;
if (write(sockfd,write_buffer,sizeof(write_buffer))!=0){
printf("Failed to send message to server\n");
exit(EXIT_FAILURE);
}
read(sockfd,read_buffer,sizeof(read_buffer));
int j=strlen(read_buffer);
read_buffer[j]='\0';
int z=0;
printf("Reversed server response:\n");
while (read_buffer[z]!='\0'){
printf("%c",read_buffer[z]);
z++;
}
}
int main(int argc, char*argv[]){
struct addrinfo hints;
struct addrinfo *result, *rp;
int cfd;
socklen_t socklen;
memset(&hints,0,sizeof(struct addrinfo));
hints.ai_family=AF_UNSPEC; //can accept IPV4 or IPV6
hints.ai_socktype=SOCK_STREAM;
hints.ai_next=NULL;
hints.ai_canonname=NULL;
hints.ai_addr=NULL;
hints.ai_flags=AI_NUMERICSERV;
char addbuff[NI_MAXSERV+NI_MAXHOST+10];
char write_buffer[MAX_MESSAGE_LENGTH];
char read_buffer[MAX_MESSAGE_LENGTH];
bzero(write_buffer,sizeof(write_buffer));
bzero(read_buffer,sizeof(read_buffer));
if (argc<2){
printf("Failed to give hostname for client");
exit(EXIT_FAILURE);
}
if ((getaddrinfo(argv[1],PORT_NUM,&hints,&result))!=0){
printf("You did not provide a legitimate host name for the client socket to search through addresses to connect to");
exit(EXIT_FAILURE);
}
for (rp=result;rp;rp=rp->ai_next){
cfd=socket(rp->ai_family,rp->ai_socktype, rp->ai_protocol);
if (cfd==-1){
continue;
}
if (connect(cfd,rp->ai_addr,rp->ai_addrlen)!=-1){
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (cfd, SOL_SOCKET, SO_ERROR, &error, &len);
if (retval==0){
printf("Socket successfully connected\n");
}
break;
}
}
chat_function(cfd,write_buffer,read_buffer);
if (rp==NULL){
printf("Could not connect socket to any address");
exit(EXIT_FAILURE);
}
close(cfd);
}
With the server running as a background process, I attempt to write to the server like so:
./client localhost (this connects the client to the socket that lives at localhost, the server)
and when I actually execute the client, I get back the error message I have in my code indicating the write through the socket in the client failed. Furthermore, when adding a print statement to the server's reversal method that outputs the length of the string it received as an arugment to reverse, it will be able to identify the string length of the string it received. This further confuses me - if my client is failing to even write through the socket, how is the server able to know the length of the word it's supposed to reverse?
try with send() and recv() instead of write() and read()
and the next problem is these functions most of the time fail when you want to get more than four byte so you need to do something like this:
(you shouldn't send or take all of them at once.
// allocate 4 byte memory for Memory2Send
Remained_Data = i;
j = 0
while (Remained_Data > 0){
if(Remained_Data > 4){
memcpy(Memory2Send, Memory4Data + j, 4;
send(Sock, Memory2Send, 4, 0);
j = j + 4;
Remained_Data = Remained_Data - 4;
}
else if(Remained_Data < 4){
memcpy(Memory2Send, Memory4Data + j, 4;
send(Sock, Memory2Send, Remained_Data, 0);
Remained_Data = 0;
}
try to send 4 bytes every round. you'll get all the data
and for server-side you need to receive 4 bytes every round.
// allocate 4 byte memory for Memory4Recv
j = 1;
z = 0;
while (j != 0) {
bzero(Memory4Recv,4);
recv(Sock, Memory4Recv, 4, 0);
for (i = 0; i < 4; i++){
Recv_Data[z] = Memory4Recv[i];
if (Recv_Data[z] == 0x00){
j = 0;
break;
}
z++;
}
}
put a null byte at the end of the reserved memory and if the size is equal to i send, i + 1;
if you want to communicate better, send more than 4 bytes each round and get a more reliable connection, you should do it on kernel-side. but first, get better in C and user-side socket programming then go for kernel-side.
Related
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;
}
i have a server/client application and i am trying to get the server to read each message the client sends to it and send it back to the client to be printed. so far i have the server reading the first message and sending that to the client and that prints fine, but when the second message is sent from the client, i try to print it from the HandleTcpClient function to test it and it just prints null, i am not sure if it is receiving it correctly
client 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;
char username[] = "CharlieA";
if (argc < 2 || argc > 3) // Test for correct number of arguments
DieWithUserMessage("Parameter(s)",
"<Server Address> [<Server Port>]");
char *servIP = argv[1]; // First arg: server IP address (dotted quad)
// Third arg (optional): server port (numeric). 7 is well-known echo port
in_port_t servPort = atoi(argv[2]); //21
printf("serv port: %d\n",servPort);
// 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_ANY;
// Establish the connection to the echo server
if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("connect() failed");
//get address of bound socket after connect function call (binds automatically with connect method)
bzero(&myaddr,sizeof(myaddr));
int len = sizeof(myaddr);
getsockname(sock,(struct sockaddr *) &myaddr, &len);
inet_ntop(AF_INET, &myaddr.sin_addr, myIP, sizeof(myIP)); //convert network address to string
myPort = ntohs(myaddr.sin_port); //convert from netshort to hostbyte order
//getlocal ip address to be sent to server
char *echoString=(char*)malloc(13*sizeof(char));
sprintf(echoString,"netsrv type0 %s %s-%u\r\n",username,myIP,myPort); //generate request string
size_t echoStringLen = strlen(echoString); // Determine input length //44
size_t iplen = strlen(myIP);
// Send the string to the server
ssize_t numBytes = send(sock,echoString, echoStringLen, 0);
printf("sent: %s", echoString);
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.
//send IP to server
send(sock,myIP,iplen,0); //send client IP
// Receive the same string back from the server //53
unsigned int totalBytesRcvd = 0; // Count of total bytes received
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("Received: ", stdout); // Setup to print the echoed 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 second message is the send client IP commented line
Server:
#include <stdio.h> //include standard input/output library
#include <stdlib.h> //include standard libraries
#include <string.h> //include string headers
#include <sys/types.h> //add definitions for constansts and functions
#include <sys/socket.h> // include definitions for different data types
#include <netinet/in.h> //define internet protocol functions
#include <arpa/inet.h> //define internet protocol functions
#include "Practical.h" //include pactical
static const int MAXPENDING = 5; // Maximum outstanding connection requests
static const int servPort = 48031;
int main(int argc) {//run on command line = "echoSvr <port>";argc = 2 command and parameter- argv[0] = echoSvr and argv[1] = <port>
// Create socket for incoming connections
int servSock; // Socket descriptor for server
if ((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithSystemMessage("socket() failed");
// this block of code is creating a socket stream to accept the incoming connections from clients
// Construct local address structure
struct sockaddr_in servAddr; // Local address; internet socket address structure
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface; host to network long[integer]
servAddr.sin_port = htons(servPort); // Local port; host to network short[integer]
// Bind to the local address
if (bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)//cast servaddr as generic socket address structure
DieWithSystemMessage("bind() failed");
// Mark the socket so it will listen for incoming connections
if (listen(servSock, MAXPENDING) < 0)
DieWithSystemMessage("listen() failed");
setvbuf (stdout, NULL, _IONBF, 0);
printf("Listening on port: %d \n" , servPort);
printf("awaiting connection from client.... \n");
// this block of code binds the socket to the address of the server and tells the binded to socket to begin listening in for connections coming from client machines
for (;;) { // Run forever
struct sockaddr_in clntAddr; // Client address
// Set length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
// Wait for a client to connect
int clntSock = accept(servSock, (struct sockaddr *) &clntAddr, &clntAddrLen);
if (clntSock < 0)
DieWithSystemMessage("accept() failed");
//this block of code waits for a client to connect to the socket and then accepts the connection from the client and prints the clients details out to screen
// clntSock is connected to a client!
char clntName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, clntName,
sizeof(clntName)) != NULL)
printf("Handling client %s/%d\n", clntName, ntohs(clntAddr.sin_port));
else
puts("Unable to get client address");
HandleTCPClient(clntSock);
}
}
HandleTCPClient Function:
void HandleTCPClient(int clntSocket) {
char buffer[BUFSIZE]; // Buffer for echo string
char *clientIP;
unsigned int clientPort;
// Receive message from client
ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if (numBytesRcvd < 0)
DieWithSystemMessage("recv() failed");
//get ip and port of clntSocket to apply to greeting string
// Send greeting string and receive again until end of stream
while (numBytesRcvd > 0) { // 0 indicates end of stream
// Echo message back to client
ssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0);
if (numBytesSent < 0)
DieWithSystemMessage("send() failed");
else if (numBytesSent != numBytesRcvd)
DieWithUserMessage("send()", "sent unexpected number of bytes");
// See if there is more data to receive
numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if (numBytesRcvd < 0)
DieWithSystemMessage("recv() failed");
//recv client ip and assign to variable to hold
recv(clntSocket,clientIP,100,0);
printf("clientIP : %s" ,clientIP);
}
close(clntSocket); // Close client socket
}
i am trying to print the clientIP with the printf function and this is where i am getting a null, it just does not seem to be receiving it, there is a lot of code here, i am posting it all in case it is needed
That is a lot of code, so I didn't look at most of it. I did, however, notice:
char *echoString=(char*)malloc(13*sizeof(char));
sprintf(echoString,"netsrv type0 %s %s-%u\r\n",username,myIP,myPort);
Nowhere do you explain where that 13 comes from, but it is clearly not enough to hold the formatted string which sprintf will produce. It's enough to hold a 12-character string (plus the NUL terminator) which gets you up to netsrv type0. That needs to be fixed, since the sprintf will clobber random memory which doesn't belong to it, but that's probably not your immediate problem. (Use snprintf. Even simpler, if you're using Linux/OSX/FreeBSD, is asprintf.)
What I think might be your problem is this:
numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
//recv client ip and assign to variable to hold
recv(clntSocket,clientIP,100,0);
printf("clientIP : %s" ,clientIP);
You never look at the data received by the first recv() call. Perhaps you are under the misapprehension that each send somehow marks the data being sent so that recv will only read exactly the data sent by one send. That's not the case. TCP is a streaming protocol; the data is just an undistinguished series of bytes and each recv() receives whatever is available, subject to the size limit in the call. So it is quite possible that the result of both send() calls will show up in the first recv() call.
I think this is probably explained in whatever text/tutorial/guide you are using to write that code, but if not I strongly recommend finding a copy of W. R. Stevens' Unix Network Programming.
In short: If you want to send "messages", you need to figure out how to delimit them in a way that the receiver can tell where one message ends and the next one begins. A really simple strategy, used by many older internet protocols, is to end each message with a newline sequence and ensure that there are no newlines in any message.
My router.c file creates 2 sockets
the first is to bind to a port and answer clients
the second is to connect to an already bound port (by the server.c file)
and send messages to.
for some reason the sendto line return an Invalid argument error.
please help.
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
/* The Rounter represents through the server file(recv_udp.c).It transmitting from/to A(client) and C(another client)
by specific criteria (given in the assignment). */
int main(int argc, char *argv[])
{
/* Adding values that`ll be used for Q5*/
char serMsg [] = "Nice to hear from you,I am the server\n";
// char serMsg [] = "Good morning sun shine\n";
int serMsgLeng = strlen(serMsg)+1;
int error = -1;
char buff_A[200] = {'\0'};
char buff_C[200] = {'\0'};
// A value we get from the command prompt
float x;
float random, rand_num;
struct timeval tv;
tv.tv_sec = 3; /* 3 Seconds Time-out */
tv.tv_usec = 0;
/* Values that`ll receive for the socket I`ll open (as socket descriptor(an int) etc.) */
int socket_fd1,socket_fd2, cc, addrLenA, s_in2Size;
/* Randome number Raffled between the range of[0,1] */
double randNum;
/* Defining Structures for decleration of the server s_in= as serverAddr(local ip,and local port),
from_A = the address that the datagram was received from client A,
from_C-the address that the datagram was received from client C . */
struct sockaddr_in s_in1, s_in2;
// Defining Structures for handling the clients address(client A and client C)
// Client A address structure
struct sockaddr_in client_A_addr;
//Client C address structure
struct sockaddr_in client_C_addr;
x = atof(argv[1]);
// Creating UDPsocket-(it`s a system call)-the socket()function opens a local socket and saves it`s number in socket_fd value. */
socket_fd1 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
socket_fd2 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/*set the socket options*/
setsockopt(socket_fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
setsockopt(socket_fd2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
// Binary cleaning /
bzero((char *) &s_in1, sizeof(s_in1)); /* They say you must do this */
bzero((char *) &s_in2, sizeof(s_in2));
/* Configure settings in address struct
"s_in.sin_family"-set the address family to be "AF_INET
"s_in.sin_addr.s_addr"- the htonl function converts host's to network's long
"s_in.sin_port" -the htons function converts regular form port to binary form.*/
s_in1.sin_family = (short)AF_INET;//host byte order
s_in1.sin_addr.s_addr = htonl(INADDR_ANY); // WILDCARD //
s_in1.sin_port = htons(1337);
s_in2.sin_family = (short)AF_INET;//host byte order
s_in2.sin_addr.s_addr = inet_addr("172.17.0.15"); // WILDCARD //
s_in2.sin_port = htons(1338);
// printsin( &s_in, "RECV_UDP", "Local socket is:");
fflush(stdout);
/* The bind function assigns a local protocol address to a socket(and another system call).
The purpose of sin here is to tell bind which local address to assign.
bind method input:the sock_fd and the stuctur that handels the address and it`s length*/
bind(socket_fd1, (struct sockaddr *)&s_in1, sizeof(s_in1));
printf("After binding,waiting to hear from clients!\n");
addrLenA = sizeof(client_A_addr);
s_in2Size = sizeof(s_in2);
connect(socket_fd2, (struct sockaddr *) &s_in2, s_in2Size);
printf("After connect to server!\n");
// Keep listenning
for(;;) {
// Check from who we recive the message - if from cilent A
// Check for errors
//recfrom() returns the length of the message that it receives,so if the client message length that the method returns is
//equal to the message length of client A - we raffel a number between[0,1].
if( (cc = recvfrom(socket_fd1,&buff_A,sizeof(buff_A),0,(struct sockaddr*)&client_A_addr,&addrLenA))== error){
printf("No message for now, waiting...\n");
}
// For self-check ,no error occured
if (strlen(buff_A) > 0) {
printf("Client A says: %s\n", buff_A);
// Than raffel a randNum and decide what to do with it(send or delete it)
srand(time(NULL));
random = rand();
rand_num = random / RAND_MAX;
printf("rand_num: %f\n", rand_num);
printf("x: %f\n", x);
// Greater than X send it
if(rand_num > x) {
printf("Sending message From A to C\n");
// Pass the message to C
if(sendto(socket_fd2, &buff_A, sizeof(buff_A),0,(struct sockaddr*)&client_C_addr,sizeof(client_C_addr))== error){
printf("sendto()- Client C failes to send message\n");
printf("%s\n", strerror(errno));
exit(1);
}
} else {
// Drop the message
}
// Clearing the message buffer
memset(buff_A, '\0', sizeof buff_A);
}
} //end for
return 0;
}
You never fill in client_C_addr. You must tell sendto where to send the data, like:
client_C_addr.sin_family = AF_INET;
client_C_addr.sin_port = htons(port);
client_C_addr.sin_addr.s_addr = inet_addr("192.168.1.1");
I am making a simple 1 to 1 server-client chat application using sockets.Basically there is a server which can communicate with a single client at a time.What I am trying to do is client should send a string to server and the server has to send it back to the client with changing the case of the string(upper to lower and vice-versa).The problem is the string is sent to the server but the response from the server never came on account of that the client is unable to send other string.
Output of the program:-
root#User:~/Desktop/Aadil/SystemPracticum/Programs/Assignment5# ./Server 4000
the message from client is message1
root#User:~/Desktop/Aadil/SystemPracticum/Programs/Assignment5# ./Client localhost 4000
enter the message message1
enter the message message2
Thank You
Here is my code
Server.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
void ChangeCase(char *string){
int i = 0;
while(string[i]){
// printf("converting\n");
if(string[i] <= 90 && string[i] >= 65)
string[i] += 32;
else
string[i] -= 32;
++i;
}
}
int main(int counter, char *string[]){
if(counter < 2){
perror("erro! please provide port no.\n");
}else{
int server_socket_file_descriptor,client_socket_file_descriptor,
port_no,message_length,client_length;
char buffer[256];//buffer to be used for storing messages
struct sockaddr_in server_address,client_address;
server_socket_file_descriptor = socket(AF_INET,SOCK_STREAM,0);
/*it creates new socket the first argument AF_INET is used for internet domain
and second argument SOCK_STREAM is used for stream socket
third argument 0 means the default protocol for stram socket which is tcp*/
if(server_socket_file_descriptor < 0)
perror("\t\t\t\t=====!!!cant create a socket!!!=====\n");
bzero((char*)&server_address,sizeof(server_address));//set all value to 0
//set port no. by converting port from char* to integer
port_no = atoi(string[1]);
/*now initialize the server_address
server_address is a struct of sockaddr_in type which has four field in it
we need to initialize 3 of them
*/
server_address.sin_family = AF_INET;
//convert port no. to network byte order
server_address.sin_port = htons(port_no);
//set server ip address to the machines ip address in my case it is 10.8.3.236
server_address.sin_addr.s_addr=INADDR_ANY;
/*now we need to bind the server with socket created*/
if(bind(server_socket_file_descriptor,(struct sockaddr*)&server_address,
sizeof(server_address)) < 0){
perror("\t\t\t\t\t====error in binding====\n");
return 0;
}
//since socket is bind correctly I am not checking for the error
listen(server_socket_file_descriptor,8);
/*listening to socket. 8 represent the maximum client that
can wait in queue to connect to the server*/
//we are done with the server :D
client_length = sizeof(client_address);
client_socket_file_descriptor = accept(server_socket_file_descriptor,
(struct sockaddr*)&client_address,
&client_length);
if(client_socket_file_descriptor < 0)
perror("\t\t\t\t unable to connect to client");
while(1){
bzero(buffer,256);
message_length = read(client_socket_file_descriptor,buffer,255);
if(message_length < 0)
perror("\t\t\t\t error in reading from socket\n");
printf("\t\t\t\tthe message from client is %s\n",buffer);
ChangeCase(buffer);
message_length = write(client_socket_file_descriptor,buffer,sizeof(buffer));
if(message_length < 0)
perror("\t\t\t\t error writing to socket\n");
}
return 0;
}
}
Client.c
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int file_descriptor,message_length,port_no;
char Buffer[256];//to store the message
//to store the address of the server to which we want to connect
struct sockaddr_in server_address;
struct hostent *server;//hostent defines the host computer on internet
if(argc < 3){
printf("\t\t\t please provide ip address and port no.\n");
return 1;
}
port_no = atoi(argv[2]);
if((file_descriptor = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
//convert port no. to network byte order
server_address.sin_port = htons(port_no);
//set server ip address to the machines ip address in my case it is 10.8.3.236
server_address.sin_addr.s_addr = INADDR_ANY;
if(connect(file_descriptor,(struct sockaddr*)&server_address,
sizeof(server_address))<0){
perror("error in connection\n");
return 1;
}
while(1){
memset(Buffer, '0',sizeof(Buffer));
printf("\t\t\t\t\tenter the message\n");
fgets(Buffer,255,stdin);
message_length = write(file_descriptor,Buffer,strlen(Buffer));
if(message_length<0)
perror("\t\t\t\terror in writing\n");
memset(Buffer,'0',sizeof(Buffer));
message_length = read(file_descriptor,Buffer,255);
if(message_length < 0)
perror("\t\t\terror in reading from buffer\n");
else{
printf("%s\n",Buffer);
}
}
return 0;
}
I suspect that the problem is located in this line in your server code:
message_length = write(client_socket_file_descriptor,buffer,sizeof(buffer));
Note that this line always sends 256 bytes back to the client. For a string like "message1", that means it will send back "MESSAGE1" followed by 248 NUL/zero bytes.
Depending on how the TCP stack decides to break up those bytes, your client's read() call may receive those bytes in different partial sequences, and if any partial sequence it receives starts with a NUL/zero byte, it will print out as an empty string.
In order to better see what's going on, you might replace this line in your client:
printf("%s\n",Buffer);
with something like this:
printf("[%s]\n",Buffer);
I'd also recommend changing your server to specify strlen(buffer) as the final argument to write() rather than sizeof(buffer).
My terminal keep create and forking . I think i did something wrong in my code, i actually want fork when client connect, but when i launch the server, its sort of keep forking as i check with linux command "ps" ,how do i change my code to make it work properly.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
using namespace std;
int main()
{
int serverFd;
int clientFd;
int serverLen;
int clientLen;
string message;
string serverSockAddrPtr;
struct sockaddr* serverSockAddressPnt;
struct sockaddr* clientSockAddressPnt;
struct sockaddr_un serverAddress;
struct sockaddr_un clientAddress;
// SOCKET CREATION PART - SERVER
serverFd = socket (AF_LOCAL, SOCK_STREAM, 0);
/* Set domain type */
serverAddress.sun_family = AF_LOCAL;
/* Set name */
strcpy (serverAddress.sun_path, "CountryServer");
/* GET SIZE OF Server Addres */
serverLen = sizeof serverAddress;
/* GET SIZE OF Client Addres */
clientLen = sizeof clientAddress;
/* Get Server Sock Address Pointer*/
serverSockAddressPnt = (struct sockaddr *) &serverAddress;
/* Get Client Sock Address Pointer*/
clientSockAddressPnt = (struct sockaddr *) &clientAddress;
/* Create file */
bind (serverFd, serverSockAddressPnt , serverLen);
/* listen for connection */
listen (serverFd,5);
// SOCKET CREATION END - SERVER
while(1)
{
//accept client connection
clientFd = accept(serverFd, clientSockAddressPnt, (socklen_t*)&clientLen);
if(fork()==0)
{
message="Successfully connected to the server";
write(clientFd,message.c_str(),strlen(message.c_str())+1);
close(clientFd);
exit(0);
}
else
close(clientFd);
}
return 0;
}
My question is:
How do i make the server to fork a process to handle client query when they connect.
I don't want it keep forking for no reasons.
Thanks for all help, this my first C coding to learn more about programming.
My client and server communicate through localhost, sockaddr_un and not internet.
What you should have for your loop is:
while (1) {
clientFd = accept(serverFd, clientSockAddressPnt, (socklen_t*)&clientlen);
if (clientFd >= 0) {
if(fork() == 0) {
message="Successfully connected to the server";
write(clientFd,message.c_str(),strlen(message.c_str())+1);
close(clientFd);
exit(0);
}
else
close(clientFd);
}
}
That way, you only ever fork when accept returns a nonnegative value (which means it completed successfully.
You should check the return value from accept(). You are getting an error, which you should fix.
The reason it keeps calling fork() is because every time you go around the loop, accept() returns (really quickly!) with an error instead of waiting for a new connection.