C++ UDP server breakdown - c++

C++ when used in networking is completely cryptic to me. Would anyone mind helping me break down the errors in this code? It was given to my class as an example of how not to make a UDP server.
I already notice a few issues like how the buffers are a fixed 256 bytes long, but for the most part I don't understand it. I'm more of a PHP/Java/JavaScript programmer.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, portno, 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 *) &cli_addr, sizeof(serv_addr));
portno = atoi(argv[2]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(cli_addr)) < 0)
error("ERROR on binding");
clilen = sizeof(cli_addr);
while(100)
{
bzero(buffer,256);
n = recvfrom(sockfd,buffer, 0, 255,
(struct sockaddr *) &serv_addr,&clilen);
printf("A client from %s port %d connected\n", inet_aton(cli_addr.sin_addr), htons(cli_addr.sin_port));
if (n < 0) error("Error reading from socket");
printf("Here is the message: %s\n",buffer);
n = sendto(sockfd,"I got your message",18,0,(struct sockaddr *) &serv_addr,sizeof(cli_addr));
if (n < 0) error("Error writing to socket");
}
close(sockfd);
return 0;
}

Have you tried it? Use nc/aka netcat to try sending UDP packets too it.
Oh and here is another clue from socket()'s man page
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length).
An you are right about the buffer size although it should not overflow - I would use 2^16 aka 65536 as this is the largest UDP packet supported in IPv4

socket function creates the socket handle for your server socket. bind function binds your socket handle to the specified IP address (INADDR_ANY) and port (via serv_addr). In your while loop, it receives data from a client via recvfrom function and prints the data out. sendto function sends the reply back to the client. close function closes your socket handle.

Related

Sockets in C++: Connection Refused (macOS)

I have an odd issue. I have been attempting to learn to use network sockets in C/C++, and I'm currently having trouble understanding why my server code does not work. I have followed a tutorial's code almost to a T, and although the example code functions fine, my code does not. I can telnet localhost 5000 to the example program just fine, but telnet simply gives me connection refused when I test my server code.
Here is my code:
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
// declare int socket descriptor and call socket() to assign to it
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
perror("Error on socket creation.");
// declare address struct
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof serv_addr);
// set values in address struct
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
// need to cast sockaddr_in to sockaddr struct
bind(sockfd, (struct sockaddr*)&serv_addr, sizeof serv_addr);
// listen on socket with num of allowed connections
if (listen(sockfd, 10) == -1)
perror("Error on listen");
int connfd;
char msg [1025];
memset(msg, 0, sizeof msg);
while (1)
{
connfd = accept(sockfd, (struct sockaddr*)NULL, NULL);
strcpy(msg, "Message lol");
write(connfd, msg, strlen(msg));
close(connfd);
sleep(1);
}
return 0;
}
This is example that functions as expected: https://pastebin.com/CG9ZWz49
And this is the tutorial I got the example from:
https://www.codeproject.com/articles/586000/networking-and-socket-programming-tutorial-in-c
Any help would be greatly appreciated. Thanks.

Simple TCP/IP client not working as expected

I am attempting to write a very basic TCP/IP client that will simply request user input, send that input to the specified IP, then read the output. The code below does not return any of the error codes but the output is still not returning as expected. For example, the device I am testing this on should respond like so:
some output here
>
Where the last ">" is returned by the device to the client to signify it is ready for more input. However, with my code all that is returned is the ">". Weirder yet, it only returns that char on every other command, with those in between returning nothing. I suspect this has to do with how I am handling the buffer; perhaps a conflict in reading the CR and/or LF chars? The device in question works perfectly over telnet (same machine, same port), and I'm not sure what I'm doing differently here. Let me know if there is any further information I can provide which might clarify my problem.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
int ethwrite(char hostname[], int portno)
{
int sockfd, n; // file descriptor, number of chars
struct sockaddr_in serv_addr; // device address
struct hostent *server; // pointer to host object
char buffer[256];
while(true)
{
// open socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) return -1; // couldn't open socket
// parse host name
server = gethostbyname(hostname);
if (server == NULL) return -2;// host not found
// zero the server address array and parse
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);
// connect to server
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
return -3; // couldn't connect
printf("Input: ");
bzero(buffer,256);
fgets(buffer,255,stdin); // take user input and write to buffer
// write command to socket
n = write(sockfd,buffer,strlen(buffer));
if (n < 0) return -4; // couldn't write to socket
// zero the buffer and read from the socket
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0) return -5; // couldn't read socket
printf("Output: %s\n",buffer);
close(sockfd); // close socket
}
return 0;
}
int main()
{
int status = ethwrite((char *)"10.13.70.230", 23);
printf("Returned status: %i\n",status);
return status;
}

how to send(serialize?) vector of float over server c++?

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!

how to display sample text in socket programming c++

I got an program that creates an socket for given port no .. i need to display an hello world text while it is accessed in browser say if the port is 8080 while visiting i need to display an hello world text using c++
prog:
#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");
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);
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;
}
Web Browsers talk HTTP when you start a URL with http:// so your server will need to talk HTTP as well.
The Browser will typically send
GET / HTTP/1.1
Host: my_website
Header1: blah blah
Header2: blah blah
The request ends with Carriage return(CR) linefeed(LN), CR LN
You will then need to create your response which will be something like
HTTP/1.1 200 OK
Content-Length: 11
Content-Type: text/plain
Hello World
With the blank line all new line having CRLN
As others have mentioned you will probably want to do something to ensure your read does not block your server.
Your code won't do that. Its going to block at the 'read(newsockfd..' until it gets input which the browser isn't going to send.
It looks like you have copied some socket server sample. It would probably be fine with the corresponding client sample but not with a browser.
If the page in the browser should display "Hello World!" then just write that instead of "I got your message".
Your example works.
Compile & run with
g++ socket.cpp
./a.out 8080
Point your browser at it:
firefox http://localhost:8080
The browser should say:I got your message
Note: You got this example from linuxhowtos.org.
Pointing people to that might also help them deduce issues.

c++: read() Hangs when reading response from server

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.