Страница 1 из 1

Клиент/Сервер, что то пропускаю, помогите;)

Добавлено: 2009-04-30 17:19:00
Pal
Всем привет.
Есть клиент:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE		4096 /* максимальная длина текстовой строки */
#define PORT		1234 /* Порт назначения */

int
main (int argc, char **argv)
{
	int sockfd, n;
	char recvline[MAXLINE + 1];
	struct sockaddr_in servaddr;

	if (argc != 2)
	{
		printf("usage: a.out <IPaddress>\n");
		exit(0);
	};

	if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) //Создание потокового сокета Интернета
	{
		perror("socket");
		exit(0);
	};

	bzero(&servaddr, sizeof(servaddr)); // Инициализация структуры нулями
	// Заполнение структуры servaddr
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(PORT); // Установка номера порта
	if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) // Установка ip адреса, значение берётся из аргумента командной строки
	{
		printf("inet_pton error for %s\n", argv[1]);
		exit(0);
	};

	if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) // Установка соединения
	{
		printf("connect error\n");
		exit(0);
	};

	while ( (n = read(sockfd, recvline, MAXLINE)) > 0) // Чтение ответа сервера
	{
		recvline[n] = 0;
		if (fputs(recvline, stdout) == EOF) // Печатаем ответ сервера
		{
			printf("fputs error\n");
			exit(0);
		};
	}
	if (n < 0)
		printf("read error\n");
	exit(0);
}
И есть сервер:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>

#define MAXLINE		4096 /* максимальная длина текстовой строки */
#define LISTENQ		1024 /* максимальное количество клиентских соединений */

int
main(int argc, char **argv)
{
	int listenfd, connfd;
	pid_t childpid;
	socklen_t clilen;
	struct sockaddr_in cliaddr, servaddr;

	char buf[MAXLINE];
	int n;

	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(1234);

	bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); // Связывает сокет с локальным адресом протокола

	listen(listenfd, LISTENQ); // Переводит сокет из состояния CLOSED в LISTEN, 1024 - максимальное число соединений, которые ядро может помещать в очередь сокета.

	printf("я родительский процесс мой pid=%d\n", getpid());

	for (;;)
	{
		clilen = sizeof(cliaddr);
		connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); // Сервер блокируется в вызове accept, ожидая подключения клиента. Возвращает новый
										  // дескриптор автоматически созданный ядром, это присоединённый сокет,
										  // используется для обращения к соединению TCP с конкретным клиентом.

		if ( (childpid = fork()) == 0)
		{
         close(listenfd);
         char buff[MAXLINE];
         time_t ticks;
         printf("Привет, я дочерний процесс и мой pid=%d\n", getpid());
         ticks = time(NULL); // Получение времени в секундах
         snprintf(buff, sizeof(buff), "%s", ctime(&ticks));  // ctime переделывает время в нормальный формат
         write(connfd, buff, strlen(buff)); // Передача данных клиенту.
         close(connfd);
         exit(0);
		}
		close(connfd);	
	}
}
Вообщем всё просто, клиент подключается к серверу, сервер форкает процесс, который будет обслуживать клиента, процесс узнаёт время и дату на тачке, передаёт всё это клиенту а клиент печатает на stdout.
Но не работает(((. Клиент просто напросто ничего не выводит. Где то что то я не вижу((( Хотя думаю, что проблема в сервере.

Спасибо

Re: Клиент/Сервер, что то пропускаю, помогите;)

Добавлено: 2009-04-30 17:23:12
paradox
тебе на сервере возращаеться connfd
и вместо того что бы в него писать
ты его закрываешь))))
круто

Re: Клиент/Сервер, что то пропускаю, помогите;)

Добавлено: 2009-04-30 17:48:14
Pal
При форканьи дескриптор дублируется а тут просто закрываю лишний, так все делают и это правильно.

Re: Клиент/Сервер, что то пропускаю, помогите;)

Добавлено: 2009-04-30 17:51:53
paradox
вообще то в него писать надо данные
это данные сокета
а ты его закрываешь и в первом и во втором
и пишешь почему то в сокет сервера
вместо того что бы писать в созданный сокет сессии клиента-сервера
тоесть в connfd нужно писать
а ты пишеь в listenfd
))))

Re: Клиент/Сервер, что то пропускаю, помогите;)

Добавлено: 2009-05-01 9:41:24
Pal
Отредактировал код:

Код: Выделить всё

      if ( (childpid = fork()) == 0)
      {
         close(listenfd);
         char buff[MAXLINE];
         time_t ticks;
         printf("Привет, я дочерний процесс и мой pid=%d\n", getpid());
         ticks = time(NULL); // Получение времени в секундах
         snprintf(buff, sizeof(buff), "%s", ctime(&ticks));  // ctime переделывает время в нормальный формат
         write(connfd, buff, strlen(buff)); // Передача данных клиенту.
         close(connfd);
         exit(0);
      }
      close(connfd);   
   }
}
Вот так вот всё работает:) А вообще если не закрывать сокет в родительском процессе, то клиент просто будет висеть. Когда дочерний процесс отработал и закрыл сокет, на самом деле сокет не закрыт, потому что дескриптор в таблице был дублирован при вызове fork.

Спасибо:)

Re: Клиент/Сервер, что то пропускаю, помогите;)

Добавлено: 2009-05-01 9:43:56
Pal
paradox писал(а): а ты пишеь в listenfd
))))
Тут я уже случайно выложил свои извращения, когда код не работает начиную всякую бредятину перебирать)