ALT Linux Community general discussions
 help / color / mirror / Atom feed
* [Comm] Q: Programming sockets in C language troubles
@ 2003-05-19 11:38 Andrey Brindeew
  2003-05-19 11:48 ` Sergey Bolshakov
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Andrey Brindeew @ 2003-05-19 11:38 UTC (permalink / raw)
  To: ALT Linux community


[-- Attachment #1.1: Type: text/plain, Size: 2401 bytes --]

Hi!

На работе встала задача перегонять данные с одной машины (расчетная,
сервер) на другую (отображение) по сети. В качестве языка используется
Си, ОС Linux, поэтому было решено использовать сокеты для передачи, дабы
ничего не изобретать ("всё уже украдено до нас" (C) :-) )

Берем тривиальный пример из документации по glibc (pinfo select, самая
последняя ссылка на странице: Server Example). Чуть-чуть дорабатываем
(избавляемся от функции make_socket путем включения ее в программу) и
пытаемся тестить:

$ gcc -o srv{,.c}
$ ./srv

На другой консоли:
$ telnet 127.0.0.1 1200
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
protocol_command 12345

Переключаемся на серверную консоль: _тишина полная_.
Нажимаем Enter три (или больше) раз - видим следующее:

$ ./srv

got message from 0 client: `
╛@пВЪ©PВЪ©└'

got message from 1 client: `
╛@пВЪ©PВЪ©└'

got message from 2 client: `
╛@пВЪ©PВЪ©└'
connect from host 127.0.0.1, port 33683.
got message from 4 client: `protocol_com─ЖЪ©L╛@L╛@ХВЪ©┼'
read: Bad file descriptor

Теперь вопросы:
 1. Почему у нас на серверной консоли фигурируют 0, 1 и 2 сокеты (я
    так понимаю, что это stdin, stdout и stderr сервера собственной
	персоной)? Я их в FD_SET не заказывал на прослушивание с помощью
	select. :-(
 2. Что за мусор идет после подстроки "protocol_com"? Я так понимаю, что
    буфер чтения у сокета заполнился (ибо 12 символов всего), но откуда
	мусор?
 3. Почему сообщение о подсоединении клиента не появилось сразу же после
    того, как я подцепился к серверу с помощью telnet?
 4. Я наверное еще много чего не понимаю, какая хорошая литература есть
    в сети и код какой _хорошо написанной_ программы можно посмотреть
	для примера? В исходниках sshd и popa3d запутался... :-(

Для желающих помочь начинающему Си-программисту советом код "сервера"
прицеплен к письму.

P.S. Первоначальная идея состояла в том, чтобы написать расчетный
     сервер, который работает по следующему протоколу: получает номер
	 алгоритма и (опционально) параметры для расчета по этому алгоритму,
	 а потом начинает тупо писать в открытый сокет рассчитываемые
	 данные, пока этот сокет удаленная сторона (визуализирующий клиент)
	 не закроет. Клиент реально будет один, но закладываться на
	 одноклиентную архитектуру при написании не хотелось бы.

-- 
WBR, Andrey Brindeew.
"No one person can understand Perl culture completely"
(C) Larry Wall.

[-- Attachment #1.2: srv.c --]
[-- Type: text/plain, Size: 2391 bytes --]

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

#define PORT 1200
#define MAXMSGLENGTH 12

int
main (void)
{
		int sock; /* server socket, which accepts new connections */
		fd_set active_fd_set, read_fd_set; /* sets of serving socket descriptors */
		int i;
		struct sockaddr_in clientname, server;
		size_t size;

		/* Create the socket and set it up to accept connections */
		sock = socket(PF_INET, SOCK_STREAM, 0);
		if (sock < 0) {
				perror("socket");
				exit(EXIT_FAILURE);
		}

		/* Give the socket a name */
		server.sin_family = AF_INET;
		server.sin_port = htons(PORT);
		server.sin_addr.s_addr = htonl(INADDR_ANY);

		if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
				perror("bind");
				exit(EXIT_FAILURE);
		}

		if (listen(sock, 10) < 0) {
				perror("listen");
				exit(EXIT_FAILURE);
		}

		/* Initialize the set of active sockets */
		FD_ZERO (&active_fd_set);
		FD_SET (sock, &active_fd_set);

		/* going into server main loop */
		while (1) {
				/* Block until unput arrives on one or more active sockets */
				read_fd_set = active_fd_set;
				if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
						perror ("select");
						exit (EXIT_FAILURE);
				}

				/* Service all sockets with input pending */
				for (i = 0; i < FD_SETSIZE; ++i) {
						if (i == sock) {
								/* Connection on server socket - new connection request */
								int new;
								size = sizeof (clientname);
								new = accept(sock, (struct sockaddr *) &clientname, &size);
								if (new < 0) {
										perror ("accept");
										exit (EXIT_FAILURE);
								}

								fprintf (stderr, "connect from host %s, port %hd.\n",
									inet_ntoa (clientname.sin_addr),
									ntohs(clientname.sin_port));
								FD_SET (new, &active_fd_set);
						}
						else {
								if (read_from_client (i) < 0) {
										close (i);
										FD_CLR (i, &active_fd_set);
								}
						}
				}
		}
}

int
read_from_client (int fd)
{
		char buffer[MAXMSGLENGTH];
		int nbytes;

		nbytes = read (fd, buffer, MAXMSGLENGTH);
		if (nbytes < 0) {
				perror("read");
				exit(EXIT_FAILURE);
		}
		else if (nbytes == 0) {
				return -1;
		}
		else {
				fprintf (stderr, "got message from %d client: `%s'\n", fd, buffer);
				return 0;
		}
}

[-- Attachment #2: Type: application/pgp-signature, Size: 245 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Comm] Q: Programming sockets in C language troubles
  2003-05-19 11:38 [Comm] Q: Programming sockets in C language troubles Andrey Brindeew
@ 2003-05-19 11:48 ` Sergey Bolshakov
  2003-05-19 11:55   ` Sergey Bolshakov
  2003-05-19 12:05 ` Sergey Vlasov
  2003-05-19 12:14 ` [Comm] " Dmitry V. Levin
  2 siblings, 1 reply; 6+ messages in thread
From: Sergey Bolshakov @ 2003-05-19 11:48 UTC (permalink / raw)
  To: ALT Linux community

>>>>> "Andrey" == Andrey Brindeew <abr@altlinux.ru> writes:

 > Hi!
 > На работе встала задача перегонять данные с одной машины (расчетная,
 > сервер) на другую (отображение) по сети. В качестве языка используется
 > Си, ОС Linux, поэтому было решено использовать сокеты для передачи, дабы
 > ничего не изобретать ("всё уже украдено до нас" (C) :-) )

 > Берем тривиальный пример из документации по glibc (pinfo select, самая
 > последняя ссылка на странице: Server Example). Чуть-чуть дорабатываем
 > (избавляемся от функции make_socket путем включения ее в программу) и
 > пытаемся тестить:
[skipped]

Первое, что приходит в голову - не надо тестить телнетом, он для
более другого предназначен. Возьмите, например, netcat.

-- 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Comm] Q: Programming sockets in C language troubles
  2003-05-19 11:48 ` Sergey Bolshakov
@ 2003-05-19 11:55   ` Sergey Bolshakov
  0 siblings, 0 replies; 6+ messages in thread
From: Sergey Bolshakov @ 2003-05-19 11:55 UTC (permalink / raw)
  To: community

>>>>> "Sergey" == Sergey Bolshakov <s.bolshakov@sam-solutions.net> writes:

>>>>> "Andrey" == Andrey Brindeew <abr@altlinux.ru> writes:
 >> Hi!
 >> На работе встала задача перегонять данные с одной машины (расчетная,
 >> сервер) на другую (отображение) по сети. В качестве языка используется
 >> Си, ОС Linux, поэтому было решено использовать сокеты для передачи, дабы
 >> ничего не изобретать ("всё уже украдено до нас" (C) :-) )

 >> Берем тривиальный пример из документации по glibc (pinfo select, самая
 >> последняя ссылка на странице: Server Example). Чуть-чуть дорабатываем
 >> (избавляемся от функции make_socket путем включения ее в программу) и
 >> пытаемся тестить:
 > [skipped]

 > Первое, что приходит в голову - не надо тестить телнетом, он для
 > более другого предназначен. Возьмите, например, netcat.

Второе, что пришло в голову :) - им и ограничиться, пуская сервер
из-под xinetd.

-- 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Comm] Q: Programming sockets in C language troubles
  2003-05-19 11:38 [Comm] Q: Programming sockets in C language troubles Andrey Brindeew
  2003-05-19 11:48 ` Sergey Bolshakov
@ 2003-05-19 12:05 ` Sergey Vlasov
  2003-05-23 11:28   ` [Comm] " Andrey Brindeew
  2003-05-19 12:14 ` [Comm] " Dmitry V. Levin
  2 siblings, 1 reply; 6+ messages in thread
From: Sergey Vlasov @ 2003-05-19 12:05 UTC (permalink / raw)
  To: ALT Linux community

On Mon, May 19, 2003 at 15:38:00 +0400, Andrey Brindeew wrote:
[skip]
>  1. Почему у нас на серверной консоли фигурируют 0, 1 и 2 сокеты (я
>     так понимаю, что это stdin, stdout и stderr сервера собственной
> 	персоной)? Я их в FD_SET не заказывал на прослушивание с помощью
> 	select. :-(

Там в цикле ещё должна была быть проверка FD_ISSET(i, &read_fd_set).

И обычно вместо FD_SETSIZE ставят max(fd) + 1, чтобы не проверялись
лишние биты.

>  2. Что за мусор идет после подстроки "protocol_com"? Я так понимаю, что
>     буфер чтения у сокета заполнился (ибо 12 символов всего), но откуда
> 	мусор?

А кто будет \0 в конце для printf добавлять?

>  3. Почему сообщение о подсоединении клиента не появилось сразу же после
>     того, как я подцепился к серверу с помощью telnet?

Так из-за отсутствия проверки FD_ISSET она и ждала ввода из stdin.

[skip]


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Comm] Q: Programming sockets in C language troubles
  2003-05-19 11:38 [Comm] Q: Programming sockets in C language troubles Andrey Brindeew
  2003-05-19 11:48 ` Sergey Bolshakov
  2003-05-19 12:05 ` Sergey Vlasov
@ 2003-05-19 12:14 ` Dmitry V. Levin
  2 siblings, 0 replies; 6+ messages in thread
From: Dmitry V. Levin @ 2003-05-19 12:14 UTC (permalink / raw)
  To: ALT Linux general discussion list

[-- Attachment #1: Type: text/plain, Size: 2288 bytes --]

On Mon, May 19, 2003 at 03:38:00PM +0400, Andrey Brindeew wrote:
> На работе встала задача перегонять данные с одной машины (расчетная,
> сервер) на другую (отображение) по сети. В качестве языка используется
> Си, ОС Linux, поэтому было решено использовать сокеты для передачи, дабы
> ничего не изобретать ("всё уже украдено до нас" (C) :-) )
> 
> Берем тривиальный пример из документации по glibc (pinfo select, самая
> последняя ссылка на странице: Server Example). Чуть-чуть дорабатываем
> (избавляемся от функции make_socket путем включения ее в программу) и
> пытаемся тестить:
> 
> $ gcc -o srv{,.c}
> $ ./srv
> 
> На другой консоли:
> $ telnet 127.0.0.1 1200
> Trying 127.0.0.1...
> Connected to 127.0.0.1.
> Escape character is '^]'.
> protocol_command 12345

$ apropos telnet netcat
telnet               (1)  - user interface to the TELNET protocol
netcat               (1)  - arbitrary TCP and UDP connections and listens

> Переключаемся на серверную консоль: _тишина полная_.
> Нажимаем Enter три (или больше) раз - видим следующее:
> 
> $ ./srv
> 
> got message from 0 client: `
> ╛@пВЪ©PВЪ©└'

Это telnet protocol, RFC 854.
[...]

> Теперь вопросы:
>  1. Почему у нас на серверной консоли фигурируют 0, 1 и 2 сокеты (я
>     так понимаю, что это stdin, stdout и stderr сервера собственной
> 	персоной)? Я их в FD_SET не заказывал на прослушивание с помощью
> 	select. :-(

А кто будет FD_ISSET делать?

>  2. Что за мусор идет после подстроки "protocol_com"? Я так понимаю, что
>     буфер чтения у сокета заполнился (ибо 12 символов всего), но откуда
> 	мусор?

Это telnet protocol, RFC 854.

>  3. Почему сообщение о подсоединении клиента не появилось сразу же после
>     того, как я подцепился к серверу с помощью telnet?

Это telnet protocol, RFC 854.

>  4. Я наверное еще много чего не понимаю, какая хорошая литература есть
>     в сети и код какой _хорошо написанной_ программы можно посмотреть
> 	для примера? В исходниках sshd и popa3d запутался... :-(

Stevens W.R. UNIX Network Programming, Volume 1, Second Edition,
Networking APIs: Sockets and XTI // Prentice Hall, Upper Saddle River,
N.J., 1998

Есть (в Москве наверняка) перевод на русский язык, но имейте в виду, что,
в отличие от перевода второго тома, перевод этого тома содержит тьму
ошибок.


--
ldv

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Comm] Re: Q: Programming sockets in C language troubles
  2003-05-19 12:05 ` Sergey Vlasov
@ 2003-05-23 11:28   ` Andrey Brindeew
  0 siblings, 0 replies; 6+ messages in thread
From: Andrey Brindeew @ 2003-05-23 11:28 UTC (permalink / raw)
  To: ALT Linux community


[-- Attachment #1.1: Type: text/plain, Size: 1100 bytes --]

On Mon, May 19, 2003 at 04:05:51PM +0400, Sergey Vlasov wrote:
> Там в цикле ещё должна была быть проверка FD_ISSET(i, &read_fd_set).

Oops, спасибо, я её пропустил при перенаборе (странно, но пара строк при
печати из pinfo пропадает - нет ни на первом, ни на втором листе!)

> И обычно вместо FD_SETSIZE ставят max(fd) + 1, чтобы не проверялись
> лишние биты.

Я не совсем понимаю, как работают указанные макросы, поэтому последовал
примеру.

> А кто будет \0 в конце для printf добавлять?
> Так из-за отсутствия проверки FD_ISSET она и ждала ввода из stdin.

Заработало, большое спасибо.
Всё работает замечательно, за исключением одного "но" - прототип клиента
вычисляет, что пропускная способность сети - 2.94Mb/sec! Никак не могу
понять, в чем я лопухнулся. gkrellm показывает 1.2-1.3M.

Время высчитываю как разницу между вызовами ntp_gettime, беру количество
принятых структур, умножаю на sizeof(принимаемая структура), делю на
время. Скорость упорно показывается ~2.94Mb/сек. :-(

Код в аттаче.

-- 
WBR, Andrey Brindeew.
"No one person can understand Perl culture completely"
(C) Larry Wall.

[-- Attachment #1.2: transfer-mini-server.tgz --]
[-- Type: application/x-gzip, Size: 3202 bytes --]

[-- Attachment #2: Type: application/pgp-signature, Size: 245 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2003-05-23 11:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-19 11:38 [Comm] Q: Programming sockets in C language troubles Andrey Brindeew
2003-05-19 11:48 ` Sergey Bolshakov
2003-05-19 11:55   ` Sergey Bolshakov
2003-05-19 12:05 ` Sergey Vlasov
2003-05-23 11:28   ` [Comm] " Andrey Brindeew
2003-05-19 12:14 ` [Comm] " Dmitry V. Levin

ALT Linux Community general discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/community/0 community/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 community community/ http://lore.altlinux.org/community \
		mandrake-russian@linuxteam.iplabs.ru community@lists.altlinux.org community@lists.altlinux.ru community@lists.altlinux.com
	public-inbox-index community

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.community


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git