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

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