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

Модератор: Fastman

Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
Pal
мл. сержант
Сообщения: 97
Зарегистрирован: 2008-07-04 14:40:14

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

Непрочитанное сообщение Pal » 2009-04-30 17:19:00

Всем привет.
Есть клиент:

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

#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.
Но не работает(((. Клиент просто напросто ничего не выводит. Где то что то я не вижу((( Хотя думаю, что проблема в сервере.

Спасибо
Последний раз редактировалось Pal 2009-05-01 10:59:54, всего редактировалось 5 раз.

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

paradox
проходил мимо
Сообщения: 11620
Зарегистрирован: 2008-02-21 18:15:41

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

Непрочитанное сообщение paradox » 2009-04-30 17:23:12

тебе на сервере возращаеться connfd
и вместо того что бы в него писать
ты его закрываешь))))
круто

Pal
мл. сержант
Сообщения: 97
Зарегистрирован: 2008-07-04 14:40:14

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

Непрочитанное сообщение Pal » 2009-04-30 17:48:14

При форканьи дескриптор дублируется а тут просто закрываю лишний, так все делают и это правильно.

paradox
проходил мимо
Сообщения: 11620
Зарегистрирован: 2008-02-21 18:15:41

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

Непрочитанное сообщение paradox » 2009-04-30 17:51:53

вообще то в него писать надо данные
это данные сокета
а ты его закрываешь и в первом и во втором
и пишешь почему то в сокет сервера
вместо того что бы писать в созданный сокет сессии клиента-сервера
тоесть в connfd нужно писать
а ты пишеь в listenfd
))))

Pal
мл. сержант
Сообщения: 97
Зарегистрирован: 2008-07-04 14:40:14

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

Непрочитанное сообщение Pal » 2009-05-01 9:41:24

Отредактировал код:

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

      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.

Спасибо:)
Последний раз редактировалось Pal 2009-05-01 10:58:06, всего редактировалось 1 раз.

Pal
мл. сержант
Сообщения: 97
Зарегистрирован: 2008-07-04 14:40:14

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

Непрочитанное сообщение Pal » 2009-05-01 9:43:56

paradox писал(а): а ты пишеь в listenfd
))))
Тут я уже случайно выложил свои извращения, когда код не работает начиную всякую бредятину перебирать)