about network programming

I test a program, but there is a problem.
About the program:
The server accepts a request and sends a message to the client.
The client connects to the server and receives a message, then prints it.

The problem is that the first time the client connected to the server does not receive the message. Instead, the message is printed on the server's terminal. But the following requests will work correctly. Why this happens ? Can any one tell me, please ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// server
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
	int sockfd, new_fd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int sin_size, portnumber;
	char hello[] = "Hello! Are You Fine?\a\n";

	if (argc != 2)
	{
		fprintf(stderr, "Usage: %s protnumber\n", argv[0]);
		exit(1);
	}

	if((portnumber = atoi(argv[1])) < 0)
	{
		
		fprintf(stderr, "Usage: %s protnumber\n", argv[0]);
	}

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		fprintf(stderr, "Usage: %s portnumber\n", strerror(errno));
		exit(1);
	}

	bzero(&server_addr, sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(portnumber);

	if(bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
	{
		fprintf(stderr, "Bind error: %s\n", strerror(errno));
		exit(1);
	}

	if(listen(sockfd, 5) == -1)
	{
		fprintf(stderr, "Listen error: %s\n", strerror(errno));
		exit(1);
	}

	while(1)
	{
		sin_size = sizeof(struct sockaddr_in);
		if (new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size) == -1)
		{
			fprintf(stderr, "Accept error: %s\n", strerror(errno));
			exit(1);
		}
		fprintf(stderr, "Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));
		if (write(new_fd, hello, strlen(hello)) == -1)
		{
			fprintf(stderr, "Write Error: %s\n", strerror(errno));
			exit(1);
		}
		close(new_fd);
	}
	close(sockfd);
	return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// client
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>


int main(int argc, char *argv[])
{
	int sockfd;
	char buffer[1024];
	struct sockaddr_in server_addr;
	struct hostent *host;
	int portnumber, nbytes;

	if (argc != 3)
	{
		fprintf(stderr, "Usage: %s hostname portnumber\n", argv[0]);
		exit(1);
	}
	if ((host = gethostbyname(argv[1])) == NULL)
	{
		fprintf(stderr, "Gethostname error\n");
		exit(1);
	}
	if ((portnumber = atoi(argv[2])) < 0)
	{
		fprintf(stderr, "Usage: %s hostname portnumber\n", strerror(errno));
		exit(1);
	}

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		fprintf(stderr, "Socket Error: %s\n", strerror(errno));
		exit(1);
	}

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(portnumber);
	server_addr.sin_addr = *((struct in_addr *)host->h_addr);

	if (connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
	{
		fprintf(stderr, "Connect Error: %s\n", strerror(errno));
		exit(1);
	}

	if ((nbytes = read(sockfd, buffer, 1024)) == -1)
	{
		fprintf(stderr, "Read Error: %s\n", strerror(errno));
		exit(1);
	}
	buffer[nbytes] = '\0';
	printf("I have received: %s\n", buffer);
	close(sockfd);
	return 0;
}
The problem is that the first time the client connected to the server does not receive the message.
The server doesn't read, it just writes and terminates the session.
Last edited on
You've a syntax error in line server/59:

new_fd will be assigned the comparison result of the result of the accept(2) operation and -1. You will get the following file descriptors:

- First connection: The fd returned from accept may usually have the value 4. This isn't equal to -1. So your new_fd gets the value 0. Depending on your startup conditions, fd=0 may be associated with your tty. And depending on your shell, fd=0 may also be open for writing. This is the reason why you'll get the output on your tty.

- Second connection: On line server/70 fd=0 was closed after processing the first connection. Now fd=0 is free. UNIX specifies to allocate the first free file descriptors from the beginning of a processes fd-table. So the next accept(2) returns 0. But this result will not be used as the new_fd! But the final comparison of (0 == -1) returns false, say 0. This is the same as the value returned by the second accept(2) call. And this is the reason why you'll finally get your output where you've intended.

Put the intended assignment within brackets then everything should work fine.
Last edited on
@kbw, @tcs, thank for your help and sorry for my late reply!
As tcs says, I have forgotten the operator precedence. Brackets should be put to ensure that = executes before == dose.
Topic archived. No new replies allowed.