I am doing a toy server-client project(on linux) where multiple clients connect to server and do remote execution on server. What I have is a select() call which is supposed to tell me when a socket is readable. This is for both listen and accept new connection. Below I am posting a snippet.
int main() {
int sockfd;
fd_set readfds;
struct sockaddr_in serv_addr,cli_addr;
struct timeval tv;
socklen_t clilen = sizeof(cli_addr);
sockfd=socket(AF_INET, SOCK_STREAM, 0);
//setsockopt(sockid,IPPROTO_IPV6,IPV6_V6ONLY,(char *)&yes,sizeof(yes));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr =inet_addr("127.0.0.1");// INADDR_ANY;
serv_addr.sin_port = htons(40000);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
perror("bind");
}
while(1)
{
FD_ZERO(&readfds);
FD_SET(sockfd,&readfds);
tv.tv_sec=2;
tv.tv_usec=500000;
int result =select(sockfd+1,&readfds,NULL,NULL,&tv);
if(result<0) {
exit(-1);
}
else if(result>0) {
if(FD_ISSET(sockfd,&readfds)) {
//int newsockfd =accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
int newsockfd =accept(sockfd,NULL,NULL);
if(newsockfd<0) {
perror("accept");
}
}
}
}
return 0;
}
But the select in the above code is always succeeding irrespective of the presence of any client and the accept is throwing error:
"accept: Invalid argument" and keep on looping, select is not even waiting for the timeout. Can someone please explain what is problem with my code. Am I not using select the right way it is supposed to be used(I am using it for the first time)?
You forgot to call listen after bind.
Related
I have two process: Server and client. Both are different sockets. Initially I execute server socket by ./server and then ./client.
But I wanted that server process should listen in background always for the request from client.
Then inplace of executing ./server, i used ./server & . This works fine in the first client call and then when i tried to connect to server it give connection failed
server.cpp
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
const char *hello = "Hello from server";
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_addr.s_addr = inet_addr("192.168.2.184");
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read( new_socket , buffer, 1024);
printf("%s\n",buffer );
send(new_socket , hello , strlen(hello) , 0 );
printf("Hello message sent\n");
return 0;
}
client.cpp
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "192.168.2.184", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
send(sock , hello , strlen(hello) , 0 );
printf("Hello message sent\n");
valread = read( sock , buffer, 1024);
printf("%s\n",buffer );
}
You have one misunderstanding with the bash comand lines ampersand (&) operator.
The trailing ampersand directs the shell to run the command in the background, that is, it is forked and run in a separate sub-shell, as a job, asynchronously. The shell will immediately return the return status of 0 for true and continue as normal, either processing further commands in a script or returning the cursor focus back to the user in a Linux terminal.
So, you invoke the program in the background and you can continue immediately to work in the shell.
But this does not mean that your program continues to run. When your program reaches its end, then its process will be terminated. The program stops.
So, what you could do (but definitely should not do) is, to call your program from the shell in a loop.
The correct way is, to build a loop in your server program and continue to accept connections. But then you need either to fork new processes or use a kind of factory, to create new TCP classes or whatever necessary to handle the requests from the client.
All this is not that simple, because the control flow of the program needs to be well designed. Linux has functions like (p)select, (p)poll or epoll to support with such atcivities.
There are also designpatterns like Reactor/Proactor/ACT available. You could implement that. But better to use an existing library.
But for testing purposes you approach is ok.
I am implementing Web Services in CPP program on WinCE.
I put a web server (HTTP), listenning on port 8080, and unitary tests works (using postman).
I put in a html page, a simple ajax request (GET) to get back a JSON array.
Init web server :
struct sockaddr_in serv_addr;
int optlen = 0;
struct timeval vtime;
SCK_ListenServerSocket = socket(AF_INET, SOCK_STREAM, 0);
if (SCK_ListenServerSocket < 0)
return (WBS_Service_Unavailable_503);
// Set receive timeout
optlen = sizeof(struct timeval);
if(getsockopt(SCK_ListenServerSocket, SOL_SOCKET, SO_RCVTIMEO, (char *) &vtime, &optlen) == -1)
{
closesocket(SCK_ListenServerSocket);
return (WBS_Service_Unavailable_503);
}
else
{
vtime.tv_sec = SCK_SRV_RECV_MS_TIMEOUT; // ms
vtime.tv_usec = 0;
if(setsockopt(SCK_ListenServerSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *) &vtime, optlen) == -1)
{
closesocket(SCK_ListenServerSocket);
return (WBS_Service_Unavailable_503);
}
}
memset((void *)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
if (bind(SCK_ListenServerSocket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
closesocket(SCK_ListenServerSocket);
SCK_ListenServerSocket = -1;
return (WBS_Service_Unavailable_503);
}
if(listen(SCK_ListenServerSocket, 1) < 0)
{
closesocket(SCK_ListenServerSocket);
SCK_ListenServerSocket = -1;
return (WBS_Service_Unavailable_503);
}
return ret;
In a thread, that function is called :
accept_socket = accept(SCK_ListenServerSocket, NULL, NULL);
if(accept_socket < 0)
n = 0;
else
{
n = recv(accept_socket, &buffer[0], 512, 0); //Read 512 bytes
DO THE WORK
}
The problem:
When I launch the web page on Chrome, the socket is opened corretly but never received. I don't know why. When I use POSTMAN it works like a charm.
Thank you for helping me.
EDIT : In that blocking socket operation, accept is called but recv is blocking. Launching a lot of request unblocks the recv, but recv response is 0 when it fails.
When I load the website on WinCE (the same target), the problem appears. When the website is loaded from my computer, and only the request is sent, no problem
I have a server which listens on certain port (fixed).
Now if that port is not available, it starts on any random port. I don't want this.
How can I make sure that if the specified port is not available, my service should not start?
int fd = ::socket(AF_INET, SOCK_STREAM, 0);
int32_t const opt = 1;
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(61014);
::bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
::listen(fd, 5);
As showed above your code won't compile. But I think you want to achieve something like the code below:
You have to check if the bind() call fails. If so than this would mean that this port is already in use. It can also happen that you already own a port, so it is recommended to use the SO_REUSEADDR flag.
if( bind(fd_desc,(struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
//print the error message
perror("Bind failed.");
return 1;
}
I'm trying to create a server socket with C++ in order to accept one client connection at a time. The program successfully creates the server socket and waits for incoming connections but when a connection is closed by the client the program would loop endlessly. Otherwise if the connection is interrupted it would keep waiting for new connections as expected. Any idea why this is happening? Thanks
This is my C++ server code:
int listenfd, connfd, n;
struct sockaddr_in servaddr, cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(32000);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 1024);
while (true) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if ((childpid = fork()) == 0) {
close (listenfd);
while (true) {
n = recvfrom(connfd, mesg, 1000, 0, (struct sockaddr *)&cliaddr, &clilen);
sendto(connfd, mesg, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
mesg[n] = 0;
printf("%d: %s \n", n, mesg);
if (n <= 0) break;
}
close(connfd);
}
}
For some reason when the client closes the connection the program would keep printing -1: even with the if-break clause..
You never close connfd in parent process (when childpid != 0), and you do not properly terminate child process that will try to loop. Your if block should look like :
if ((childpid = fork()) == 0) {
...
close(connfd);
exit(0);
}
else {
close(connfd);
}
But as you say you want to accept one connection at a time, you can simply not fork.
And as seen in other answers :
do not use mesg[n] without testing n >= 0
recvfrom and sendto are overkill for TCP simply use recv and send (or even read and write)
mesg[n] = 0;
This breaks when n<0, ie. socket closed
The problem is your "n" and recvfrom. You are having a TCP client so the recvfrom won't return the correct value.
try to have a look on :
How to send and receive data socket TCP (C/C++)
Edit 1 :
Take note that you do the binding not connect() http://www.beej.us/guide/bgnet/output/html/multipage/recvman.html
means there is an error in recieving data, errno will be set accordingly, please try to check the error flag.
you've written a TCP server, but you use recvfrom and sendto which are specific for connection-less protocols (UDP).
try with recv and send. maybe that might help.
I have a socket that listens on some port.
I send the SIGSTOP signal to the thread that waits on the port (using accept) and terminate it. then I close the fd of the socket that I waited on. But for the next run of my project it doe's not allow me to listen on that port again.
My program is in C++ under linux.
What should I do?
Some parts of my code are:
Thread 1:
void* accepter(void *portNo) {
int newsockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
}
struct sockaddr_in server;
bzero((char *) & server, sizeof (server));
server.sin_family = AF_INET;
server.sin_port = htons(*(int*) portNo);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *) & server, sizeof (struct sockaddr_in)) < 0) {
perror("ERROR on binding");
}
listen(sockfd, 50);
while (true) {
struct sockaddr_in client;
socklen_t clientLen = sizeof (struct sockaddr_in);
newsockfd = accept(sockfd, (struct sockaddr *) & client, &clientLen);
if (accepterFlag) {
break;
}
if (getpeername(newsockfd, (sockaddr *) & client, &clientLen) == -1) {
perror("getpeername() failed");
}
sem_wait(setSem);
FD_SET(newsockfd, &set);
if (maxFd < newsockfd) {
maxFd = newsockfd;
}
sem_post(setSem);
}
Thread 2:
listenerFlag = true;
accepterFlag = true;
sleep(1);
pthread_kill(listenerThread, SIGSTOP);
pthread_kill(accepterThread, SIGSTOP);
close(sockfd);
sem_wait(setSem);
for (int i = 1; i <= maxFd; i++) {
if (FD_ISSET(i, &set)) {
close(i);
}
}
sem_post(setSem);
Thank you.
Did you know that sockets are typically kept in a kind of limbo for a minute or two after you've finished listening on them to prevent communications intended for the previous process coming to yours? It's called the 'TIME_WAIT' state.
If you want to override that behaviour use setsockopt to set the SO_REUSEADDR flag against the socket before listening on it.
I think the problem is that you have not properly closed the socket and/or your program.The socket probably still exists in the OS. check it with something like nestat -an. You should also check if your process has exited. If it has correctly ended, it should have closed your socket.
What you should do is :
interrupt your thread with a signal.
when interrupted your thread should cleanly close the socket before the end.
then you can cleanly exit from your program.
my2cents,