Reputation: 731
I have a simple socket program created in C (using Ubuntu), the connection works fine, server compiles and client provides the IP and port number.
But when the connection is established, the client can only send one message
and then the connection closes
. When the client sends the message, the server receives it and the program ends by itself
.
I tried to use a while loop
, but then it gives me an Error on binding
. Is there any way to make it infinite, so that when user enters exit
or some specific key/command
, the program ends.
server.c UPDATED with WHILE LOOP
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portNum, clien, n;
char buffer[256];
struct sockaddr_in serv_addr,cli_addr;
if (argc < 2)
{
fprintf(stderr, "\nno port provided");
exit(1);
}
sockfd = socket(AF_INET,SOCK_STREAM, 0);
if (sockfd < 0)
printf("\nprovide a valid port number\n");
bzero((char *)&serv_addr, sizeof(serv_addr));
portNum = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portNum);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
printf("error on binding");
while(1)
{
listen(sockfd,5);
}
clien = sizeof(cli_addr);
newsockfd=accept(sockfd, (struct sockaddr *) &cli_addr, &clien );
if (newsockfd < 0)
printf("=> Error on accepting...\n");
bzero(buffer, 256);
n = read(newsockfd, buffer, 256);
if (n < 0)
printf("error reading from socket...\n");
printf("%s\n", buffer);
n = write(newsockfd, "message received.", 58);
if (n < 0)
printf("cannot write from socket...\n");
return 0;
}
client.c UPDATED with WHILE LOOP
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
int main(int argc, char *argv[])
{
int sockfd,portno,n;
char buffer[256];
struct sockaddr_in serv_addr;
struct hostent *server;
//while(counter != 5)
// /{
if (argc < 3)
{
fprintf(stderr,"Usage %s hostname port...\n",argv[0]);
exit(1);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("\error opening socket...\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr,"no such host...\n");
exit(0);
}
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, &serv_addr,sizeof(serv_addr)) <0 )
printf("\error connecting\n");
printf("your message:");
fgets(buffer, 256, stdin);
while(1)
{
n = write(sockfd,buffer,strlen(buffer));
}
if (n < 0)
printf("error writing to socket\n");
n = read(sockfd, buffer, 255);
if (n < 0)
printf("error reading from socket\n");
printf("%s\n", buffer);
return 0;
}
Thank you.
Upvotes: 2
Views: 12698
Reputation: 3456
The problem with your server is that you immediately terminate whenever you receive a message. What you should do is keep on listening with the recv() function until the client disconnects. Here is one piece of code that should do the trick.
Disclaimer: However I haven't tested it, it's from an old project that I modified for you on the fly it's supposed to work but I'm not 100% sure it does, I have no time to test it right now but feel free to ask questions if there is something wrong, I'll try to correct it.
EDIT: trying to re-bing causes an error because the binding is already done and the port is already busy so you cannot "assign" an other program to this port therefore giving you an error. The only thing that you have to do is make sure that your server listens until the client disconnects from the server.
Also, it is possible that some of the code was made for c++ at some point, but the networking part should work just fine.
Feel free to try it out and comment if you have questions. Server.c:
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
//HANDLE ERROR
}
printf("Socket created\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8000 );
//Binding, you already do it correctly.
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server))< 0)
{
//ERROR
}
printf("bind done");
//Listen
listen(socket_desc , 3);
printf("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = (int*) malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
//ERROR
}
printf("Handler assigned");
}
if (client_sock < 0)
{
//ERROR
}
//return 0;
}
/*
* This will handle connection for each client you may have and read indefinitely
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char *message , client_message[2000];
string smatrix ;
int ind ;
string tok ;
int i = 0 ;
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
//What you want to do with the client's message
}
if(read_size == 0)
{
printf("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
//ERROR
}
//Free the socket pointer
free(socket_desc);
As for the client, do a while loop until a certain time has passed or a given character or value is entered. Something like:
while(wantToExit == false){
char a;
printf("Please enter a char");
scanf("%c", &a);
write(sock , a , 1); //Note use strlen() for strings
}
Hope it helps
Upvotes: 2
Reputation: 12263
What do you actually expect the server to do? You open/read/terminate. Termination, of course closes the socket implicitly - luckily, as you forgot to close explicitly.
You have to constantly read from the socket. Not sure what you mean by "it ...gives me an Error on binding"; if you try to re-bind, that is of course wrong. You would not open a file again and again, and ... just to read its data.
If you want to listen on the socket after it has been closed from the other side, just have listen
in an outer loop.
Read Wikipedia for basics about sockets and check the links.
Upvotes: 1