I'm developing client-server software. On server's side I use this code:
int listener_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listener_socket < 0)
{
perror("opening socket error");
return;
}
/* set option for reuseaddr */
int mtrue = 1;
if(setsockopt(listener_socket,SOL_SOCKET,SO_REUSEADDR,&mtrue,sizeof(int)) != 0)
{
perror("setsockopt error");
return;
}
struct sockaddr_in serv_addr, cli_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
bzero((char *) &cli_addr, sizeof(cli_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* bind socket */
if (bind(listener_socket,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
{
perror("binding error");
return;
}
/* start listening */
listen(listener_socket,connections_limit);
int newsockfd;
/* infinite cycle */
while(1){
newsockfd = accept(listener_socket,(struct sockaddr*) &cli_addr,&clilen);
...
}
So my code blocks in accept() method and waiting for the new connection. When client connects, accept method returns correct non-negative socket descriptor (i can communicate with client using this descriptor) but it doesn't fill cli_addr structure. It remains zeroes. Why it happens?
i forgot this line before accept:
clilen = sizeof(cli_addr);
Related
I want to make a client and connect it to a server. I know that client process starts running before server so I do connection in infinite loop until it will be accept. Then I want to enter messages to client and send them to server, which will print them on screen. I removed all error detection from code to make it shorter, I know they have to be there. I am trying to do it like this, but server receives nothing and client can't do second connection.
Server
int main(int argc, char *argv[])
{
int sockfd, newsockfd;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(5000);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
listen(sockfd, 5);
clilen = sizeof(cli_addr);
while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0)
{
read(newsockfd, buffer, 255);
close(newsockfd);
}
close(sockfd);
return 0;
}
Client
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr;
char buffer[256];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(5000);
while (1) {
while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) {
printf("trying to connect\n");
sleep(1);
}
printf("connected\nplease, enter a message\n");
scanf("%s", buffer);
write(sockfd, buffer, strlen(buffer));
}
close(sockfd);
return 0;
}
I don't know just how you've compiled your code but if you had set up the warning flag (-Wall in gcc) you would have gotten this warning
server.c: In function ‘main’:
server.c:33:44: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) {
Acting by it, I changed, this ..
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) {
To .. (notice the extra parentheses)
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) {
I got no more additional warnings, and the server caught the client's message.
Here is the server I ran while debugging this (This is basically your code with slight alterations)
int sockfd, newsockfd;
socklen_t clilen;
char buffer[256];
int nbytes = 0;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
//serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(5007);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (listen(sockfd, 5) <0) { }
clilen = sizeof(cli_addr);
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) {
while ((nbytes = read(newsockfd, buffer, sizeof(buffer)))<0) {
sleep(1);
}
printf("client sent: %s", buffer);
}
close(newsockfd);
close(sockfd);
return 0;
Another problem was that we have to create socket each time we do connect in client, like:
while (1) {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) {
printf("trying to connect\n");
sleep(1);
}
printf("connected\nplease, enter a message\n");
scanf("%s", buffer);
write(sockfd, buffer, strlen(buffer));
}
Hello I'm sending requests in cycle and then processing them, I have to make that until the program's not stopped by the user. I have to use UDP and after testing on localhost after 1020 requests I get error in gethostbyname, it returns NULL
int sockfd, portno, n, serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
portno = my_port;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
server = gethostbyname(my_host);
bzero(buf, BUFSIZE);
if (sockfd < 0) {
error("ERROR opening socket");
}
if (server == NULL) {
fprintf(stderr,"ERROR, no such host as %s\n", my_host);
exit(0);
}
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serveraddr.sin_addr.s_addr, server->h_length);
serveraddr.sin_port = htons(portno);
serverlen = sizeof(serveraddr);
n = sendto(sockfd, packet, myArraySize, 0, (struct sockaddr *)&serveraddr, serverlen);
if (n < 0) {
error("ERROR in sendto");
}
n = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *)&serveraddr, &serverlen);
if (n < 0) {
error("ERROR in recvfrom");
}
I found nothing about this behavior, and if I'm not using the localhost then I get the error after just 120 requests.
Most likely explanation is that each process on your system is only allowed to have 1024 open file descriptors at a time. 3 of those are reserved for stdin, stdout and stderr.
So the problem is that each time you call gethostbyname, you create a new sockfd, but the code doesn't close the socket when it's done with it.
This is a simple iterative client-server program. Where the server prints out "Received request" on successful establishment of connection.
server side
#define LENGTH 256
#define SERV_PORT 4000
#define LISTENQ 8
int main()
{
int listenfd, connfd, n;
socklen_t clilen;
char buf[LENGTH];
struct sockaddr_in cliaddr, servaddr;
//creation of socket
listenfd = socket (AF_INET, SOCK_STREAM, 0);
//creating socket address
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
// printf("\nServer running.. waiting for connections");
// listen(listenfd, LISTENQ);
for(; ;)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("\nReceived request");
//sleep(5);
}
return 0;
}
client side
#define LENGTH 256
#define SERV_PORT 4000
int main( int argc, char *argv[])
{
int sock;
struct sockaddr_in server;
struct hostent *hp;
char buff[256];
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket failed");
exit(1);
}
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if(hp == 0)
{
perror("gethost by name failed");
exit(1);
}
memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
server.sin_port = htons(4000);
if(connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
{
perror("\nconnect failed");
exit(1);
}
return 0;
}
When I run this multiple client-server code, the output for first client is different from the preceding clients. I need the first client to output like others. Can someone help?
When the first client establishes a connection with the server, the server doesn't output "Received request", where as, for the other clients do output "Received request".
You need to restore the listen() call. – EJP
I have a server-client system (concurrent server). I have different clients on different machines. I am trying to send a notification to particular clients. However, I have a problem as the clients all have the same socket descriptor. On both computers, the clients have a socket descriptor of 3 and at the server a sd of 5. Can someone please tell me how I can identify these different clients and why is this happening?
int main(int argc, char *argv[]) {
pid_t pid;
int buff_size = 1024;
char buff[buff_size];
int listen_fd, client_conn;
struct sockaddr_in serv_addr;
int server_port = 5001;
char remote_file[255];
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("Socket cannot be opened");
exit(1);
}
/*Turning off address checking in order to allow port numbers to be
reused before the TIME_WAIT. Otherwise it will not be possible to bind
in a very short time after the server has been shut down*/
int on = 1;
int status = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &on, sizeof(on));
if (status == -1) {
perror("Failed to Reuse Address on Binding");
}
// Initialise socket structure
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY; // Accept connections from any address
serv_addr.sin_port = htons(server_port);
// Bind the host address
if (bind(listen_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
< 0) {
perror("ERROR on binding");
exit(1);
}
// Start listening for the clients, here process will
// go in sleep mode and will wait for the incoming connection
listen(listen_fd, 5);
while (1) {
//Accepting client connection
client_conn = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (client_conn < 0) {
perror("Client was not accepted...");
exit(1);
}
if ((pid = fork()) == 0) {
close(listen_fd);
bzero(buff, buff_size);
while ((bytes_read = read(client_conn, buff, buff_size)) > 0) {
fclose(file);
}
}
//Terminating child process and closing socket
close(client_conn);
exit(0);
bzero(buff, buff_size);
}
//parent process closing socket connection
close(client_conn);
}
return 0;
}
After the server forks a child it does close(client_conn). When accept assigns a socket descriptor to the new connection, it uses the lowest closed descriptor. Since you closed the socket earlier, it can be used for the next client that comes in.
This isn't a problem, because the connections are being managed by the child processes. They each have their own descriptor 5, and they don't interfere with each other.
You can get the client address & port returned to you by accept. Currently you are passing a null
client_conn = accept(listen_fd, (struct sockaddr *) NULL, NULL);
however just add a few lines like
struct sockaddr_in serv_addr, cli_addr;
int len = sizeof(cli_addr);
client_conn = accept(listen_fd, (struct sockaddr *) &cli_addr, &len);
and you have the client info in cli_addr.sin_addr.s_addr and cli_addr.sin_port.
You can get the pid of the child processing the connection from the return code of fork. That should give you all the information you need to create a table.
For some reason my recvfrom() function for sockets is not blocking on my server code like it is supposed to. I am making a basic UDP server to create a rolling session key system.
What am I doing wrong here? It continues on after this line (before i put the (n < 1)) and was crashing. I am pretty sure recvfrom() is supposed to stop the execution of the program until it gets something from the client...
int sockfd, portNumber;
socklen_t clilen;
char buffer[BUFFER_LENGTH];
struct sockaddr_in serv_addr, from;
int n;
// Invalid arguments
if (argc < 2)
exit(0);
else if (atoi(argv[1]) > 65535 || atoi(argv[1]) < 1)
exit(0);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("Error opening socket.\n");
exit(0);
}
// Taken from reference
bzero((char *) &serv_addr, sizeof(serv_addr));
portNumber = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portNumber);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
printf("ERROR on binding.\n");
close(sockfd);
exit(0);
}
// Get initial session key request
int fromlen = sizeof(struct sockaddr_in);
n = recvfrom(sockfd, buffer, BUFFER_LENGTH, 0, (struct sockaddr *)&from, &fromlen);
if (n < 0)
{
printf("Error in receiving.\n");
exit(1);
}
Thanks
You're trying to use a stream socket for UDP;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
What you mean to do is probably;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
Trying to do recvfrom on an unconnected stream socket will most likely return immediately with an error. Next time, you may want to check errno for a hint.