I'm a beginner in programming in c++ with a bit of experience in java.
My goal is transfer files (in local host) between a server and a client (in two different folders).
I have found this code online that works well for me, it opens sockets and makes a connection between the server and the client and you can send a message typed in the terminal.
I have tried a lot of different codes on the INTERNET and either it doesn't compile or it isn't what I need.
Here is a code that I found that works to transmit a message.
server.cpp file
enter code here
/* 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>
void error(const char *msg)
{
perror(msg);
exit(1);
}
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");
exit(1);
}
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,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}
client.cpp file
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
I'm compiling with g++ in ubuntu.
I'd love if you could help me to at least be able to send a txt file from the client or download a file from the server, as soon as i try to add functionalities in this code nothing works anymore, maybe I'm starting with a bad example?
you should try this example, it works good for me
receive:
size_t datasize;
FILE* fd = fopen(filename, "wb");
while (!received)
{
datasize = recv(connection, text, sizeof(text), 0);
fwrite(&text, 1, datasize, fd);
}
fclose(fd);
send:
FILE *fd = fopen(filename, "rb");
size_t rret, wret;
int bytes_read;
while (!feof(fd)) {
if ((bytes_read = fread(&buffer, 1, BUFFER_SIZE, fd)) > 0)
send(sock, buffer, bytes_read, 0);
else
break;
}
fclose(fd);
Good luck:)
Related
I'm a newbie in socket programming. I'm trying to make a server/ client program to download a file.
Firstly, i init some step that i usually do in other program for set up a connection form client to server.
Next, From server side, I'm try to in put number of bytes that send to client to set up the receive buffer's size. From client side, I receive the number in string type. I convert it to long type and set it to buffer size.
Then, From client side, I enter the name of file that need to download from server. Server receive the name and check if it exist or not.
Last step ( THE PROBLEM STEP, i think ) server try to open file. if file is opened, send the file name back to client. client check file name if it same what it sent or not.
======> my problem is file name sent back to client:
- From server side: I print it out and check. it's correct.
- From client: I print buffer out right after read from server. It's not correct. sometimes, it's empty. sometimes, it's some-random-value.
I have done exactly like previous step.
Server.cpp
#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 <string>
using namespace std;
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
perror("you have to input port");
exit(1);
}
// init sockfd
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("sockfd perror");
exit(1);
}
// sockopt
int opt = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
// init server
bzero(&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);
// bind port
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
char buffer[256];
// write buff size
int buffsize;
printf("Input recive buffsize in Byte: ");
scanf("%d", &buffsize);
if (buffsize <= 0)
{
perror("Buffer size must be > 0");
exit(1);
}
bzero(buffer, sizeof(buffer));
bcopy(to_string(buffsize).c_str(), buffer, sizeof(buffer));
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("fail to send buffer size");
exit(0);
}
//read file name
bzero(buffer, sizeof(buffer));
n = read(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
// open file:
char filename[strlen(buffer) + 1];
bcopy(buffer, filename, sizeof(filename));
FILE *pf;
unsigned long fsize;
pf = fopen(filename, "rb");
if (pf == NULL)
{
bzero(buffer, sizeof(buffer));
bcopy("File not found", buffer, sizeof(buffer));
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
printf("File not found!\n");
return 1;
}
else
{
printf("File %s is openned \n", filename);
fseek(pf, 0, SEEK_END);
fsize = ftell(pf);
rewind(pf);
printf("File has %ld bytes!\n", fsize);
}
// write OK response file name
bzero(buffer, sizeof(buffer));
bcopy(filename, buffer, sizeof(buffer));
printf("\n\n\n\n%s\n\n\n\n", buffer);
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
close(newsockfd);
close(sockfd);
return 0;
}
Client.cpp
#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>
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
if (argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
// init sockfd
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("sockfd error");
exit(1);
}
// init server
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(portno);
// connect
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR connecting");
exit(1);
}
// recive and set buffer size:
char tempBuff[10];
bzero(tempBuff, 10);
n = read(sockfd, tempBuff, sizeof(tempBuff));
if (n < 0)
{
perror("fail to recive buffer size");
exit(1);
}
char buffer[stol(string(tempBuff))];
printf("Connect succes, Buffer size is %ld Bytes\n", sizeof(buffer));
// input file:
printf("Input file name to download: ");
string filename;
cin >> filename;
// Send filename
bzero(buffer, sizeof(buffer));
bcopy(filename.c_str(), buffer, filename.length());
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
}
// read file name response
bzero(buffer, sizeof(buffer));
n = read(sockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR reading from socket");
}
printf("\n\n\n\n%s, %ld\n\n\n\n", buffer, strlen(buffer));
// if (strcmp(buffer, filename.c_str()) == 0)
// {
// printf("OK!\n");
// }
// else
// {
// perror("Wrong filename");
// printf("server msg: %s\n", buffer);
// exit(1);
// }
close(sockfd);
return 0;
}
RUN CODE WITH FOLLOWING COMMAND:
Client: ./client [server ip] [port]
Server: ./server [port]
My result:
Update 1: problem disappear when i remove these line:
// write buff size
int buffsize;
printf("Input recive buffsize in Byte: ");
scanf("%d", &buffsize);
if (buffsize <= 0)
{
perror("Buffer size must be > 0");
exit(1);
}
at server.cpp
and these line:
// recive and set buffer size:
bzero(tempBuff, sizeof(tempBuff));
n = read(sockfd, tempBuff, sizeof(tempBuff));
if (n < 0)
{
perror("fail to recive buffer size");
exit(1);
}
// char buffer[stol(string(tempBuff))];
at client.cpp
I solved it. this problem occur due to tempBuff is too small. it's just 10 bytes. Using bigger tempBuff will solve the problem.
i am setting up a web server in c++. I need to return from server a feature vector in the form of vector. I see that the socket doesn't allow such object to pass through directly, but need to serialize it. I am trying to serialize it by converting my vector result to a char* a. but when i do curl request, it still get back nothing.
Would anyone let me know the trick here?
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
// server.cpp
#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 <vector>
#include <iostream>
void error(const char *msg)
{
perror(msg);
exit(1);
}
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,5);
while (1 == 1) {
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("before result: %s\n",buffer);
std::vector<float> fv;
fv.push_back(7);
fv.push_back(8);
char* result = reinterpret_cast<char*>(&fv);
send(newsockfd, result, sizeof(result), 0);
//n = write(newsockfd,"I got your message",18);
//if (n < 0) error("ERROR writing to socket");
printf("message sent. \n");
close(newsockfd);
//close(sockfd);
}
return 0;
}
To compile the code:
g++ -o server server.cpp
And run:
./server 8080
For curl request:
curl http://localhost:8080
And i get:
alliey:socket alliey$ curl http://localhost:8080
`N�.
How should i interpret the response?
i figure it out, by simply send raw data:
send(newsockfd, result.data(), sizeof(result[0])*result.size(), 0);
On the client side, i used python struck.unpack to receive the result. It works pretty well.
But still thanks for all the tips above!
Here is my code for a node.js TCP server hosted on both Heroku and AppFog. My client was written in C and it simply sends a message to the server and get the response. When I host the server on local, they work fine. But when I try to connect to the online server, the client fails("ERROR connecting: Operation timed out"). Any idea what happened?
Server(node.js):
var net = require('net');
var server = net.createServer(function (socket) {
socket.on("data", function(data){
socket.write(data.toString());
});
});
var port = process.env.VCAP_APP_PORT || 8081;
console.log(port);
server.listen(port);
Client(C, from http://www.linuxhowtos.org/C_C++/socket.htm):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
while (1){
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
}
close(sockfd);
return 0;
}
The client must always connect on port 80 regardless of what process.env.VCAP_APP_PORT is set to. AppFog proxies requests from port 80 to the port your app is running on.
I am sorry if the title is misleading. I cannot really think of a better one. Here is some simple socket program that I have:
#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 <sys/poll.h>
#include <iostream>
#define BACKLOG 10
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);
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
int portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
auto bindsuccess = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (bindsuccess < 0)
error("ERROR on binding");
struct pollfd newPollFD[1];
newPollFD[0].fd = sockfd;
newPollFD[0].events = POLLIN;
char buffer[256];
bzero(buffer,256);
listen(sockfd, BACKLOG);
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
int newsockfd;
int rv = poll(newPollFD, 1, -1);
if (rv == -1) {
error("Error occured in Poll");
}
else {
if (newPollFD[0].revents & POLLIN){
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
int rwsuccess;
rwsuccess = read(newsockfd,buffer,255);
if (rwsuccess < 0)
error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
rwsuccess = write(newsockfd,"I got your message \n",18);
if (rwsuccess < 0)
error("ERROR writing to socket");
}
}
close(newsockfd);
close(sockfd);
return 0;
}
If I execute this code with a port number, and then telnet to that port number, the server listens in, but as soon as I send my first message, the connection terminates. I want the sever to keep on listening and sending acknowledgement back as many times as I send message from telnet. How do I accomplish that?
Thanks in advance!
The continue is curiously extraneous, and causes the compilation to break. (It is now corrected in your edit.) But, you are missing a for loop. And, you should add a check if the read returns 0.
for (;;) {
int rwsuccess;
rwsuccess = read(newsockfd,buffer,255);
if (rwsuccess < 0)
error("ERROR reading from socket");
if (rwsuccess == 0) break;
printf("Here is the message: %s\n",buffer);
rwsuccess = write(newsockfd,"I got your message \n",18);
if (rwsuccess < 0)
error("ERROR writing to socket");
}
I have two versions of this code. In one version if the user inputs the phrase "GET /index.html" the server responds properly. In the second version, the "GET /index.html" phrase is built in without prompting the user. The second version hangs when reading a response from the server, any idea why?
First Version - Prompts user for phrase
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(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[10000];
portno = atoi("85");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char *)"ERROR opening socket");
server = gethostbyname("vilive.us");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error((char *)"ERROR connecting");
printf("Please enter the message: ");
memset(buffer,0,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error((char *)"ERROR writing to socket");
memset(buffer,0,256);
n = read(sockfd,buffer,500);
if (n < 0)
error((char *)"ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
Second Version - Automatically sends "GET /index.html" - This one hangs
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(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[10000];
//TEST
char getI[16];
getI[0]='G';
getI[1]='E';
getI[2]='T';
getI[3]=' ';
getI[4]='/';
getI[5]='i';
getI[6]='n';
getI[7]='d';
getI[8]='e';
getI[9]='x';
getI[10]='.';
getI[11]='h';
getI[12]='t';
getI[13]='m';
getI[14]='l';
getI[15]='\0';
portno = atoi("85");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char *)"ERROR opening socket");
server = gethostbyname("vilive.us");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error((char *)"ERROR connecting");
/*printf("Please enter the message: ");
memset(buffer,0,256);
fgets(buffer,255,stdin);*/
n = write(sockfd,getI,strlen(getI));
if (n < 0)
error((char *)"ERROR writing to socket");
memset(buffer,0,256);
n = read(sockfd,buffer,500);
if (n < 0)
error((char *)"ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
The request must be terminated with 2 carriage return and line feed pairs, this is missing in your second example.
char charI[] = "GET /index.html\r\n\r\n";
Please, switch to a modern version of HTTP. I find it amazing that your server agrees to reply, as the request isn't remotely valid HTTP.
This would be a suitable HTTP/1.1 request in your situation
char charI[] = "GET /index.html HTTP/1.1\r\nHost: vilive.us\r\nConnection: close\r\n\r\n";
note the Host header, that allow you to talk with sites that do virtual hosting, like ... stackoverflow.com and superuser.com that points to the same ip address. they only rely on the Host header to figure out if the user want to access stackoverflow.com or superuser.com.
Also, your should close the socket descriptor when you are done using the socket.