I have a C++ application which receives 1 char and runs a function dependent on which char it has received. The problem is that the application stops as soon as it has received one message.
I need the application to start listening on the same port again after it has received a message but I haven't managed to do so. I tried looping it with a "while (true)" loop but I get errors.
It may also be worth noting that after the server has ran successfully it gives the message:
** * stack smashing detected ***: terminated
Aborted (core dumped)
And if I try to run the server again on the same port after it has successfully completed I get:
ERROR on binding: Address already in use
Significant code:
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1];
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");
if (buffer[0] == '0') {
lamp();
}
else {
printf("No valid input from client.\n");
}
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}
EDIT: I should've mentioned that I am very new to C++. Please give an example with your solution.
char buffer[1]; ... bzero(buffer,256);
Of course, after you've corrupted the whole stack it's understandable that other reasonable code is suddenly failing.
Related
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!
I'm developing a chat program over TCP to allow me to communicate between two machines over WAN. I'm pretty new to C++ (coming from Java) and am very new to TCP, so don't go too hard on me! (: I've looked around on a fair amount of tutorials and continue to find only Echo programs, nothing that can leave a connection open for an extended amount of time to allow a chat like function. My current code looks like this:
#include "ClientManager.h"
ClientManager::ClientManager() {
}
void ClientManager::connectCom(char* ipAdd) {
portno = atoi(PORT);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(ipAdd);
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");
}
void ClientManager::message(std::string msg) {
// printf("Please enter the message: ");
char * buffer = new char[msg.size() + 1];
std::copy(msg.begin(), msg.end(), buffer);
buffer[msg.size()] = '\0';
// 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);
bzero(buffer,256);
}
void ClientManager::closeCom() {
close(sockfd);
}
void ClientManager::error(const char *msg)
{
perror(msg);
exit(0);
}
and my server manager looks like this:
#include "ServerManager.h"
ServerManager::ServerManager() {
// int sockfd, portno, n;
// struct sockaddr_in serv_addr;
// struct hostent *server;
}
void ServerManager::openCom() {
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
socklen_t clilen;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(PORT);
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");
}
int ServerManager::readCom() {
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");
if (buffer[0] == '0')
return 1;
return 0;
}
void ServerManager::closeCom() {
close(newsockfd);
close(sockfd);
}
void ServerManager::error(const char *msg) {
perror(msg);
exit(1);
}
Both of these classes are implemented by separate main functions who call the functions necessary. I know that the code itself is ok for sending a single message- its been doing that for awhile now. Its just when client calls more than one message() that I experience errors, specifically, a segmentation fault. This only happens on the second message, the first one is sent and received appropriately.
If anyone could help me out, it would be greatly appreciated. Thanks!
In ClientManager::message you forget to delete the buffer at the end of the method.
ALternatively, you should declare the buffer on the local stack as this:
char buffer[msg.size() + 1];
As such, the buffer will be automatically deallocated by the end of the call.
And reading later code, you better do:
char buffer[256];
I think the code for reading the server's reply causes buffer overrun if your msg.size() < serverReply.size, even if you think you have 256 characters (you simply didn't allocated them at method start) . Please take care to this buffer length declaration and later handling, as C++ would let you write beyond it's end, corrupting neighbouring variables and leading to segfaults.
I'm trying to build a client -> proxy server -> server application.
I need help with the proxy server, how do i make it send data to the server right now it can only communicate with the client.
Here is my codef or the proxy server, I modified it from an example. I'm new at this.
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
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);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
/******** DOSTUFF() *********************
There is a separate instance of this function
for each connection. It handles all communication
once a connnection has been established.
*****************************************/
void dostuff (int sock)
{
int n, p;
char buffer[256];
char request;
FILE *file;
file = fopen("process.log","a+");
do
{
//here the proxy server receives data from the client
bzero(buffer,256);
p = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("num: %s\n",buffer);
//here the proxy servers replies to the client.
n = write(sock,buffer,sizeof(buffer));
//here the process should send data to the server
//...codes i need help with...
if (n < 0) error("ERROR writing to socket");
fprintf(file,"%s\n",buffer); /*writes*/
}while(p != 0); //this runs the process +1 more than it should. wonder why?
fclose(file);
}
DoStuff() .... you can also check the comments I added.
Also how do I send a message to the client as soon as the client is connected to the server, something like a welcome client message? :)
note: the proxy server sends a GET request to a HTTP 1.1 server.
I would really appreciate it. Thanks :)
To connect to the server, you're going to have to call socket and then connect to get that socket connected to your real server from the proxy. See section 5 here:
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
Additionally, check p instead of n 4 lines into your do-while loop in DoStuff().
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");
}
if (strcmp(buffer,"change work")==0)
{
close(newsockfd); /*closing the old port*/
close(sockfd);
printf("Changing port to 51717....\n");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi("51717");
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) /*binding with the new port*/
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");
printf("port changed\n");
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");
}
else
{
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);
}
In the above code when the condition is satisfied, both the codes are being executed instead of code1. This loop is not working properly. what may be the reason???
I want to focus on if part.
Two approaches to solving this:
a). Step in a debugger, you're quite likely to see that your code isn't quite as you think.
b). replace your complex code with a simple construct.
if (strcmp(buffer,"change work")!=0)
{ printf("yes") }
else
{ printf("no"); }
You will see that this works just fine, then make incremental changes to turn it back into your real code, at some point you'll go "aha".
Edited in light of your last comment:
My guess is that buffer does not contain exactly "change work" but perhaps also a newline character or other such delimiter. You would probably be benefit from adding diagnostic trace statements to show the buffer contents, use java.util.logging or log4j.