I'm wondering how to convert a char[] array to a char *
For example, in my code I am trying to access a web server using a hostname like "example.com"
Using my code, if I set a char * to "example.com" like below, it works perfectly.
char *host = "example.com";
But, what I really want to do is be able to read from a client program using a socket, write to a char[] array, and use the data obtained from that as the hostname.
For example,
char buffer[4096], hostname[4096];
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
wbhost = gethostbyname(hostname);
when my code gets to the last line, it just sits there, so I'm thinking its a typing problem, since when I do this:
char *host = "example.com";
...
wbhost = gethostbyname(host);
It works, and is able to get the data from the web and send it properly to my client program.
Any ideas are appreciated.
In the client program I use fgets() to read into a char[] from stdin then use write() to write to the socket for the server program to read. I had tried to use strcat() to add '\0' to the end of the char[] before writing to the socket but that didn't seem to do anything
Full Code: (Please ignore the comments, just trying different things for now)
client
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int sockfd, portnum, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[4096];
if(argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
portnum = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("ERROR opening Socket");
exit(1);
}
server = gethostbyname(argv[1]);
if(sockfd == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portnum);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR, on connecting");
exit(1);
}
printf("Please enter the Host name: ");
bzero(buffer, 4096);
fgets(buffer, 4095, stdin);
//strcat(buffer, "\0");
n = write(sockfd, buffer, strlen(buffer));
if(n < 0)
{
printf("Error writing to socket");
exit(1);
}
bzero(buffer, 4096);
n = read(sockfd,buffer, 4095);
if(n < 0)
{
printf("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
server
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portnum, clilen;
char buffer[4096], hostname[4096];
pid_t p_id;
struct sockaddr_in serv_addr, cli_addr;
int n, pid, hostname_len;
//char *host;
char *host = "example.com";
if(argc < 2)
{
fprintf(stderr, "ERROR, NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);//socket is made
if(sockfd < 0)
{
fprintf(stderr, "ERROR opening socket!!");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portnum = atoi(argv[1]);//port num
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnum);
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR on binding");
exit(1);
}
if( listen(sockfd, 5) < 0)
{
printf("ERROR ON LISTEN");
exit(1);
}
// accept
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if(newsockfd < 0)
{
fprintf(stderr, "ERROR on accept\n");
exit(1);
}
pid = fork();
if(pid == 0)
{
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
if(n < 0)
{//message from client
fprintf(stderr, "ERROR Reading from socket\n");
exit(1);
}
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
//variables used for acsessing webserver?
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
if(sockwb < 0)
{
printf("Error opeing websocket\n");
exit(1);
}
// hostname_len = sizeof(hostname) / sizeof(hostname[0]);
// printf("%d\n", hostname_len);
// memcpy(host, hostname, hostname_len);
// host[hostname_len] = '\0';
printf("%s\n", host);
// hostname[hostname_len] = '\0';
// host = &hostname[0];
//wbhost = gethostbyname(hostname);
wbhost = gethostbyname(host);
//printf("%s", wbhost->h_name);
printf("here2\n");
/*if(wbhost == NULL)
{
printf("NO SUCH web HOST\n");
exit(1);
}
*/
bzero((char*) &webser_addr, sizeof(webser_addr));
webser_addr.sin_family = AF_INET;
bcopy((char *)wbhost->h_addr, (char *)&webser_addr.sin_addr.s_addr, wbhost->h_length);
webser_addr.sin_port = htons(wbport);
// printf("here3\n");
if(connect(sockwb, (struct sockaddr *) &webser_addr,sizeof(webser_addr)) < 0)
{
printf("Error on web connecting\n");
exit(1);
}
bzero(webbuf, 4096);
strcpy(webbuf, "GET / HTTP/1.0\r\nHost: ");
// strcat(webbuf, hostname);
strcat(webbuf, host);
strcat(webbuf, "\r\nConnection: close\r\n\r\n");
// const char * request = "GET / HTTP/1.0\r\nHost: example.com\r\nConnection: close\r\n\r\n";
// printf("%s\n", request);
// x = write(sockwb, request, strlen(request));
printf("%s\n", webbuf);
x = write(sockwb, webbuf, strlen(webbuf));
if(x < 0)
{
printf("Error writing to web sock");
exit(1);
}
bzero(webbuf, 4096);
x = read(sockwb, webbuf, 4096);
if(n < 0)
{
printf("Error reading from web socket");
exit(1);
}
printf("%d\n", (int)strlen(webbuf));
printf("%s\n",webbuf);
n = write(newsockfd, webbuf, 4095 );//write back to client
if(n < 0)
{
fprintf(stderr, "ERROR WRITING to socket");
exit(1);
}
//printf("%s\n", webbuf);
}//end of if pid==0
printf("closing client");
close(newsockfd);//closing client socket
}while(1);
return 0;
}
The code you posted runs unimpeded. When you ask for help, you should always post a complete, verifiable example. Check that the code you post actually reproduces the problem!
Looking at what the code does, it seems that in the server, you meant to use the host name that you read as the argument to gethostbyname. You can do that with
host = &hostname[0];
or simpler
host = hostname;
or by not using two separate variables in the first place.
When you use an array in a context that expects a value (as opposed to e.g. taking its address or its sizeof), the array decays into a pointer to its first element. So here hostname is equivalent to hostname[0].
After that change, check the trace closely, or, to make the problem more visible, change the tracing line to
printf("[%s]\n", hostname);
You'll see
[aaa.com
]
The client reads a line with fgets, which includes the terminating newline character in its count. The client dutifully forwards the complete line to the server. And so the server looks up a host name containing a newline character, which doesn't exist. You don't check the return code of gethostbyname (you should!), it returns a null pointer, and the program crashes when it tries to read from it.
#Gilles is right, you have an '\n' at the end of the hostname, the following piece of code replaces the '\n' by 0 which is the equivalent of the character '\0':
extern int h_errno;
...
hostname[strlen(hostname) - 1] = 0;
wbhost = gethostbyname(hostname);
if (!wbhost) {
printf("Failed! %s\n", strerror(h_errno));
exit(1);
}
...
A char[] is an array of chars. A char* is a pointer to a char - generally (but not always) the start of a string.
If you want to get a pointer to the start of your array, you don't even need to do anything! This conversion happens implicitly:
char hello[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
// or: char hello[] = "hello"; (equivalent to above)
printf("%s", hello); // prints hello
puts(hello); // also prints hello
char *hello2 = hello;
puts(hello2); // also prints hello
Probably the easiest way to 'convert' char[] to char * is:
char example_array[] = "example";
char * example_pointer = (char *)calloc(1, strlen(example_array) + 1); // + 1 for the '\0' character
strcpy(example_pointer, example_array);
Related
I have been trying to write a client and server program using C socket programming that does 2 tasks
On prompted from server -> OS command is executed in client machine
Output is stored in a file which is sent back to server. Where server reads it and displays the data plus writes the data in a file on server side.
Issue
When client sends file to the server, server does not display whole data and looks like recv() keeps waiting on socket.
Need some help
Here's the code
server code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define SIZE 1024
void write_file(char *filename,int sockfd){
int n;
FILE *fp ;
char buffer[SIZE] ;
fp = fopen(filename, "w");
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0){
break;
return;
}
printf("%s", buffer) ;
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
fclose(fp) ;
return;
}
int main(int argc, char *argv[]){
int portno = 7416;
int e,n,n1;
char *cmd ;
int sockfd;
struct sockaddr_in server_addr;
struct hostent *server;
char *fle = "/tmp/reposvr.";
FILE *fp;
char *num ;
if (argc < 3) {
fprintf(stderr,"usage %s hostname command \n", argv[0]);
exit(0);
}
cmd=argv[2] ;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
//server_addr.sin_family = AF_INET;
//server_addr.sin_port = port;
//server_addr.sin_addr.s_addr = inet_addr(ip);
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portno);
server_addr.sin_addr = *((struct in_addr *)server->h_addr);
memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero);
e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e == -1) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Connected to Server.\n");
n = write(sockfd, cmd , strlen(cmd));
if (n < 0)
error("ERROR writing to socket");
char *filename=NULL;
filename = (char*)malloc( 50 * sizeof(char) ) ;
strcpy(filename,fle );
n1=rand();
if (asprintf(&num, "%d", n1) == -1) {
perror("asprintf");
} else {
strcat(filename, num);
printf("%s\n", filename);
free(num);
}
printf("%s\n",filename) ;
write_file(filename,sockfd) ;
printf("[+]File data sent successfully.\n");
printf("[+]Closing the connection.\n");
close(sockfd);
return 0;
}
Client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024
void send_file(FILE *fp, int sockfd){
int n;
char data[SIZE] = {0};
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
int main(){
int port = 7416;
int e,n1, n ;
FILE *fp ;
char filename[50] = "/tmp/gateway." ;
char command[50];
char *num;
FILE *pf;
char data[SIZE];
int sockfd, new_sock;
struct sockaddr_in server_addr, new_addr;
socklen_t addr_size;
char buffer[SIZE];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
e = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e < 0) {
perror("[-]Error in bind");
exit(1);
}
printf("[+]Binding successfull.\n");
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
perror("[-]Error in listening");
exit(1);
}
addr_size = sizeof(new_addr);
while ( new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size) )
{
printf("server: got connection from %s port %d\n",
inet_ntoa(new_addr.sin_addr), ntohs(new_addr.sin_port));
n = read(new_sock,buffer,1024);
if (n < 0) error("ERROR reading from socket");
strcpy(command, buffer) ;
printf("%s",command) ;
pf = popen(command,"r");
bzero(data,1024);
n1=rand();
if (asprintf(&num, "%d", n1) == -1) {
perror("asprintf");
} else {
strcat(filename, num);
printf("%s\n", filename);
free(num);
}
printf("%s",filename) ;
fp=fopen(filename,"w" );
while (fgets(data, 2048, pf) != NULL) {
printf("%s", data);
fprintf(fp, "%s",data) ;
}
fclose(fp) ;
fp = fopen(filename, "r");
if (fp == NULL) {
perror("[-]Error in reading file.");
exit(1);
}
send_file(fp, new_sock);
printf("[+]Data written in the file successfully.\n");
}
return 0;
}
Execution output
Edit
Based on the suggestions in this forum, I increased SIZE to 2048 and found that now it returns less rows and hangs after 4-5 rows itself. This is weird. I am sure it's not because of SIZE.
If you see, in client side, we are able to successfully write all in a file. Second part of the program is to read from file and send it to server. Here I am iterating through whole file and sending the data to server. The data send loop is working nicely as I have printf in same loop and we can see all data getting printed.
Looking at server side, here also we are looping till number of bytes read are < 1. Theoretically, this should work. I am sure there's some tiny silly thing that I am missing. Just not able to put my finger on it. Really need some insights in here.
Edit 2
Already tried SIZE , MSG_PEEK as you can see in comments. Any more suggestions ?
I'm currently learning socket programming in C on linux system. I got a sample code of server, and I'm having problem of running it properly. It looks like this:
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXCONNECTION 100 // maximum number of simultaneously connection allowed
const char CONTENTDIR[]="./contentdir" ; // this is the directory where keep all the files for requests
void error(const char *msg)
{
perror(msg);
exit(1);
}
void httpWorker(int *);// This function will handle request
char * fType(char *);
char * responseHeader(int, char *);// function that builds response header
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
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");
listen(sockfd,MAXCONNECTION);
while(1){
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
httpWorker(&newsockfd);//worker to fulfillthe request
}
close(sockfd);
return 0;
}
void httpWorker(int *sockfd){//sockfd contains all the information
int newsockfd = *sockfd;// create a local variable for sockfd
char buffer[256];// we will read the data in this buffer
char *token;// local variable to split the request to get the filename
bzero(buffer,256);// intialize the buffer data to zero
char fileName[50];
char homedir[50];
char * type;
strcpy(homedir,CONTENTDIR);// directory where files are stored.
char *respHeader; //response header
// start reading the message from incoming conenction
if (read(newsockfd,buffer,255) < 0) error("ERROR reading from socket");
//get the requested file part of the request
token = strtok(buffer, " ");// split string into token seperated by " "
token = strtok(NULL, " ");// in this go we read the file name that needs to be sent
strcpy(fileName,token);
// get the complete filename
if(strcmp(fileName,"/")==0) // if filename is not provided then we will send index.html
strcpy(fileName,strcat(homedir,"/index.html"));
else
strcpy(fileName,strcat(homedir,fileName));
type = fType(fileName);// get file type
//open file and ready to send
FILE *fp;
int file_exist=1;
fp=fopen(fileName, "r");
if (fp==NULL) file_exist=0;
respHeader = responseHeader(file_exist,type);
if ((send(newsockfd, respHeader,strlen(respHeader), 0) == -1) || (send(newsockfd,"\r\n", strlen("\r\n"), 0) == -1))
perror("Failed to send bytes to client");
free(respHeader);// free the allocated memory (note: the memory is allocated in responseheader function)
if (file_exist){
char filechar[1];
while((filechar[0]=fgetc(fp))!=EOF){
if(send(newsockfd,filechar,sizeof(char),0) == -1) perror("Failed to send bytes to client");
}
}
else{
if (send(newsockfd,"<html> <HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY>Not Found</BODY></html> \r\n", 100, 0) == -1)
perror("Failed to send bytes to client");
}
close(newsockfd);
}
// function below find the file type of the file requested
char * fType(char * fileName){
char * type;
char * filetype = strrchr(fileName,'.');// This returns a pointer to the first occurrence of some character in the string
if((strcmp(filetype,".htm"))==0 || (strcmp(filetype,".html"))==0)
type="text/html";
else if((strcmp(filetype,".jpg"))==0)
type="image/jpeg";
else if(strcmp(filetype,".gif")==0)
type="image/gif";
else if(strcmp(filetype,".txt")==0)
type="text/plain";
else
type="application/octet-stream";
return type;
}
//buildresponseheader
char * responseHeader(int filestatus, char * type){
char statuscontent[256] = "HTTP/1.0";
if(filestatus==1){
strcat(statuscontent," 200 OK\r\n");
strcat(statuscontent,"Content-Type: ");
strcat(statuscontent,type);
strcat(statuscontent,"\r\n");
}
else {
strcat(statuscontent,"404 Not Found\r\n");
//send a blank line to indicate the end of the header lines
strcat(statuscontent,"Content-Type: ");
strcat(statuscontent,"NONE\r\n");
}
char * returnheader =malloc(strlen(statuscontent)+1);
strcpy(returnheader,statuscontent);
return returnheader;
}
What I've done was to build a sub directory called contentdir under the folder where I put this server.c file, then I tried to get connetion from my browser ( I guess it doesn't matter with the browser). I just typically ran it by ./server 8080 and put localhost:8080/(and whatever the name of files in contentdir). It shows me black screen on the browser instead of the file contents. It stops connecting after reached MAXCONNECTION attmepts, I guess. I have tried html and jpg files, both no work.
Can someone help me to figure it out please?
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.
I have a program that creates a socket (server and client program) and sends a message via a TCP port using that socket. My question is, how can I exchange multiple messages?
Every time I send a message the port gets closed and I need to use another port to send another message.
For example, I have to send 2 numbers from the client to the server and the server needs to reply back the total sum of the numbers I send. How would I achieve sending undefined number or even 2 numbers over the SAME port?
Here are the codes (pretty much standard stuff):
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
char* Itoa(int value, char* str, int radix)
{
static char dig[] =
"0123456789"
"abcdefghijklmnopqrstuvwxyz";
int n = 0, neg = 0;
unsigned int v;
char* p, *q;
char c;
if (radix == 10 && value < 0) {
value = -value;
neg = 1;
}
v = value;
do {
str[n++] = dig[v%radix];
v /= radix;
} while (v);
if (neg)
str[n++] = '-';
str[n] = '\0';
for (p = str, q = p + (n-1); p < q; ++p, --q)
c = *p, *p = *q, *q = c;
return str;
}
void error (const char *msg)
{
perror (msg);
exit (1);
}
int main (int argc, char *argv[])
{
if (argc < 2)
{
fprintf (stderr, "ERROR, no port provided\n");
exit (1);
}
//nova varijabla za sumiranje primljenih brojeva
int suma=0;
int sockfd, newsockfd, portno,i;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
for (i=0;i<2;i++)
{
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error ("ERROR opening socket");
memset ((char *) &serv_addr, 0, sizeof (serv_addr));
portno = atoi (argv[1]);
portno+=i;
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");
//test za ispis otvorenog porta
printf("Uspjesno otvoren localhost na portu %d\n", portno);
listen (sockfd, 5);
clilen = sizeof (cli_addr);
newsockfd = accept (sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error ("ERROR on accept");
memset (buffer, 0, 256);
n = read (newsockfd, buffer, 255);
if (n < 0) error ("ERROR reading from socket");
printf ("%d. proslan broj: %s\n", i+1, buffer);
//print
suma=suma+atoi(buffer);
//radi!! printf("suma je %d\n", suma);
//od klijenta: n = write (sockfd, buffer, strlen (buffer));
//char * itoa ( int value, char * str, int base );
Itoa(suma, buffer, 10);
n = write (newsockfd, buffer, strlen(buffer));
if (n < 0) error ("ERROR writing to socket");
close (newsockfd);
close (sockfd);
}
return 0;
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error (const char *msg)
{
perror (msg);
exit (1);
}
int
main (int argc, char *argv[])
{
if (argc < 3)
{
fprintf (stderr, "usage %s hostname port\n", argv[0]);
exit (1);
}
int sockfd, portno, n,i;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
for (i=0;i<2;i++)
{
portno = atoi (argv[2]);
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error ("Ne mogu otvoriti socket!");
server = gethostbyname (argv[1]);
if (server == NULL)
{
fprintf (stderr, "Greska, ne postoji!\n");
exit (1);
}
memset ((char *) &serv_addr, 0, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy ((char *) server->h_addr,
(char *) &serv_addr.sin_addr.s_addr,
server->h_length);
portno+=i;
serv_addr.sin_port = htons (portno);
if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error ("ERROR connecting");
printf ("%d. broj za slanje: ", i+1);
memset (buffer, 0, 256);
fgets (buffer, 255, stdin);
n = write (sockfd, buffer, strlen (buffer));
if (n < 0)
error ("ERROR writing to socket");
memset (buffer, 0, 256);
n = read (sockfd, buffer, 255);
if (n < 0)
error ("ERROR reading from socket");
if (i==1) printf ("Suma iznosi: %s\n", buffer);
close (sockfd);
}
return 0;
}
So, for example, I run the code and get this for the server side:
j#PC ~/Desktop/Mreze/Lab1/rijeseno $ ./server2 5000
Uspjesno otvoren localhost na portu 5000
1. proslan broj: 45
Uspjesno otvoren localhost na portu 5001
2. proslan broj: 56
j#PC ~/Desktop/Mreze/Lab1/rijeseno $
And on the client side:
j#PC ~/Desktop/Mreze/Lab1/rijeseno $ ./client2 localhost 5000
1. broj za slanje: 45
2. broj za slanje: 56
Suma iznosi: 101
I've tried putting a while loop so it loops the part with sending but without success. Please explain to me where should I even put it so it works. Thank you!
Here is a problem:
n = read (newsockfd, buffer, 255);
What you do, is you perform read once, and the data might not be fully available. The fact is, you need to read data, as long as you received the data completely, or detected EOF condition (-1 return value).
Generally you need to write more reliable code for receiving part, as it is not guaranteed on stream protocol that your message boundaries are kept in any form.
Here is a (very unoptimal, yet simple) code for reading data:
int readLine(int fd, char data[])
{
size_t len = 0;
while (len < maxlen)
{
char c;
int ret = read(fd, &c, 1);
if (ret < 0)
{
data[len] = 0;
return len; // EOF reached
}
if (c == '\n')
{
data[len] = 0;
return len; // EOF reached
}
data[len++] = c;
}
}
And usage example:
char buffer[256];
int num1, num2;
readLine(newsockfd, buffer);
num1 = atoi(buffer);
readLine(newsockfd, buffer);
num2 = atoi(buffer);
First Put your connection() function before and close() after for loop. Just for an idea
connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)
for (i=0;i<n;i++){
// do you introspection with server
// actually send number to server
}
// Code to read result: SUM from server
close (sockfd);
First and foremost, thank you all for reading this and helping, I'm very grateful.
Second I'm sorry but i'm still new to this site and English is not my mother language so I could do some formatting and language mistakes. I apologize in advance.
Also, my C knowledge is not that good, but i'm willing to learn and improve.
Now, to the matter at hand:
What I need to do is to create a Client and a Server, and have the server listen for incoming connections.
Then I have the Client send a quite big text file (I know it will only be ONE file) to the Server.
The Server will then do some operation on the file (it will run a script on the sent file that produces another file in output called "output.txt").
The server then will need to send the output.txt file back to the Client.
Now, I kinda got how to make a Client and a Server (I read beej guide and some other stuff on this site), even tho I probably made some mistakes. I need some help with the server reciving the file, then calling the script and sending the other file back to the client.
For now what I did is the Server and Client... I don't really know how to go on.
On a side note, I made this files using what I found on this site and on the internet, I hope they are not too messy, as I'm not that good of a programmer.
This is client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#define SOCKET_PORT "50000"
#define SOCKET_ADR "localhost"
#define filename "/home/aryan/Desktop/input.txt"
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main()
{
/* Making the client */
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
portno = atoi(SOCKET_PORT);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(SOCKET_ADR);
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");
/* Time to send the file */
FILE *pf;
unsigned long fsize;
pf = fopen(filename, "rb");
if (pf == NULL)
{
printf("File not found!\n");
return 1;
}
else
{
printf("Found file %s\n", filename);
fseek(pf, 0, SEEK_END);
fsize = ftell(pf);
rewind(pf);
printf("File contains %ld bytes!\n", fsize);
printf("Sending the file now");
}
while (1)
{
// Read data into buffer. We may not have enough to fill up buffer, so we
// store how many bytes were actually read in bytes_read.
int bytes_read = fread(buffer, sizeof(char),sizeof(buffer), pf);
if (bytes_read == 0) // We're done reading from the file
break;
if (bytes_read < 0)
{
error("ERROR reading from file");
}
// You need a loop for the write, because not all of the data may be written
// in one call; write will return how many bytes were written. p keeps
// track of where in the buffer we are, while we decrement bytes_read
// to keep track of how many bytes are left to write.
void *p = buffer;
while (bytes_read > 0)
{
int bytes_written = write(sockfd, buffer, bytes_read);
if (bytes_written <= 0)
{
error("ERROR writing to socket\n");
}
bytes_read -= bytes_written;
p += bytes_written;
}
}
printf("Done Sending the File!\n");
printf("Now Closing Connection.\n");
fclose(pf);
close(sockfd);
return 0;
}
This is server.c:
#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 <signal.h>
#include <pthread.h>
#define SOCKET_PORT 50000
#define filename "/home/aryan/Desktop/output.txt"
void error(const char *msg)
{
perror(msg);
exit(1);
}
void* client_thread_proc(void* arg)
{
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
FILE *fp;
int thisfd = (int)arg;
printf("Server %d: accepted = %d\n", getpid(), thisfd);
if (thisfd < 0)
{
printf("Accept error on server\n");
error("ERROR on accept");
return NULL;
}
printf("Connection %d accepted\n", thisfd);
fp = fopen(filename, "a+b");
if (fp == NULL)
{
printf("File not found!\n");
return NULL;
}
else
{
printf("Found file %s\n", filename);
}
/* Time to Receive the File */
while (1)
{
bzero(buffer,256);
n = read(thisfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
n = fwrite(buffer, sizeof(char), sizeof(buffer), fp);
if (n < 0) error("ERROR writing in file");
n = write(thisfd,"I am getting your file...",25);
if (n < 0) error("ERROR writing to socket");
} /* end child while loop */
fclose(fp);
return NULL;
}
void serve_it(int Client)
{
void* arg = (void*)Client;
pthread_t new_thread;
pthread_create( &new_thread, NULL, &client_thread_proc, arg);
}
/* Making Server */
int main()
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
FILE *fp;
signal (SIGCHLD, SIG_IGN);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening 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(SOCKET_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1)
{
printf("Server %d accepting connections\n", getpid());
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
serve_it(newsockfd);
} // serving loop
close(sockfd);
return 0;
}
I'd like some pointers on how to go on...
How do I make a script go on the file i received from client to server?
How do I send the new file back to the same client?
And if you could help me with the errors in the code i'd be grateful.
Thank you all and sorry for the long read. Have a nice day!
First error:
#define filename = "Home\\Desktop\\input.txt"
should be
#define filename "Home\\Desktop\\input.txt"
Otherwise the preprocessor inserts the
= "Home\Desktop\input.txt"
not the
"Home\\Desktop\\input.txt"
that you expect.
Second error:
int bytes_read = read(filename /* THAT IS WRONG, FILE HANDLE MUST BE HERE */, buffer, strlen(buffer) /* also WRONG, must be MAX_BYTES_IN_BUFFER or something */ );
Here you must read from "pf" (you've opened it with the fopen() call) and the last argument must be the number of bytes you want to read. So if you do the strlen(buffer) and the buffer contains some garbage at the beginning of the program's runtime you will get a crash. strlen() must only be called for valid zero-terminated string, it is not the size of the array !
EDIT: elaborated server's loop:
while (1)
{
printf("Server %d accepting connections\n", getpid());
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
serve_it(newsockfd);
} // serving loop
The serve_it():
void serve_int(int Client)
{
void* arg = (void*)Client;
pthread_t new_thread;
pthread_create( new_thread, NULL, &client_thread_proc, arg);
}
void* client_thread(void* arg)
{
int thisfd = (int)arg;
printf("Server %d: accepted = %d\n", getpid(), thisfd);
if (thisfd < 0)
{
printf("Accept error on server\n");
error("ERROR on accept");
return NULL;
}
printf("Connection %d accepted\n", thisfd);
fp = fopen(filename, "a+b");
if (fp == NULL)
{
printf("File not found!\n");
return NULL;
}
else
{
printf("Found file %s\n", filename);
}
/* Time to Receive the File */
while (1)
{
bzero(buffer,256);
n = read(thisfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
n = fwrite(buffer, sizeof(buffer), 1, fp);
if (n < 0) error("ERROR writing in file");
n = write(thisfd,"I am getting your file...",25);
if (n < 0) error("ERROR writing to socket");
} /* end child while loop */
return NULL;
}