LINUX.ORG.RU

неблокируемый сокет. туплю.


0

0

делаю select для пачки сокетов. далее

while (lenr = read (pch->sock, buff, 1) > 0)

если по 1му байту, то все работает. как только выставляю объем чтения не 1, а размер буфера (32К), то ничерта не работает. внутрях while сделал lenr - в случае если размер буфера ставлю 1 - то цикл срабатывает много раз и принтует «1» много раз. Если ставлю использую read (pch->sock, buff, BUFFER_LEN), то принтует только один раз и все. боле ничего.

чет уже нифига не понимаю. господа, наведите на путь истиный, а? чет уже голова не соображает.

Deleted

то принтует только один раз и все

Ну а сколько должно раз печатать? В 32к как раз один пакет и влезет. Непонятно, что не так.

боле ничего.

Это что такое - боле ниче? Блокируется, из цикла выходит, что именно? Если блокируется - O_NONBLOCK.

Вообще кинь сюда strace, сразу все видно будет.

vga ★★
()
Ответ на: комментарий от Deleted

Я всегда думал, что читать с сокета надо не размер буфера, а столько,
1. ...сколько на сокете доступно байт для чтения
2. ...сколько требует протокол

Сколько данных-то приходит на сокет?

yoghurt ★★★★★
()
Ответ на: комментарий от vga

>>1. ...сколько на сокете доступно байт для чтения

это через либастрал ты узнаешь, или как? :-)

Через WSAIoctl под виндой и fnctl под юниксами.

yoghurt ★★★★★
()
Ответ на: комментарий от vga

вот собсно сам исходник

		fdmax++;
		tv.tv_sec = 0;
		tv.tv_usec = 20000;
		
		lenr = select (fdmax, &fds, NULL, NULL, &tv);

		if (lenr == -1)
			continue;

		lst = tunnel->channel_list;

		do
		{
			pch = lst->data;
			
			if (FD_ISSET (pch->sock, &fds))
			{
				memset (buff, 0, CHANNEL_BUFF);

				while (lenr = read (pch->sock, buff, 1) > 0)
				{
					lenw = channel_write (pch->channel, buff, lenr);
					g_debug ("lenr = %d", lenr);

					if (lenw == SSH_ERROR)
					{
						g_debug ("channel_write return SSH_ERROR. remove it.");

						rem = lst;
				
						GSQLP_TUNNEL_LOCK(tunnel);
						lst = g_list_previous (lst);
						GSQLP_TUNNEL_UNLOCK(tunnel);
				
						tunnel_channel_remove (tunnel, rem);
						break;
					}

					pch->tx += lenw;
				}

				if ((lenr == -1) && (errno == EAGAIN))
				{
					g_debug ("eagain.....");
						GSQLP_TUNNEL_LOCK(tunnel);
						lst = g_list_previous (lst);
						GSQLP_TUNNEL_UNLOCK(tunnel);
						continue;
				}

				if (lenr == -1)
				{
					g_debug ("error. removing....");
						rem = lst;
				
						GSQLP_TUNNEL_LOCK(tunnel);
						lst = g_list_previous (lst);
						GSQLP_TUNNEL_UNLOCK(tunnel);

						tunnel_channel_remove (tunnel, rem);

						continue;
				}
				    

			} 

			GSQLP_TUNNEL_LOCK(tunnel);
			lst = g_list_previous (lst);
			GSQLP_TUNNEL_UNLOCK(tunnel);

		} while (lst);

Deleted
()
Ответ на: комментарий от yoghurt

О блин, век живи, век учись, спасибо, может и пригодится когда. Но делать лишний сискол таки не буду, проще буфер дать.

vga ★★
()
Ответ на: комментарий от Deleted

Ну исходник это хорошо, а стрейс? И еще, насколько я понял по g_debug, это glib? У них там есть чудесное асинхронное IO, почему бы его и не использовать для этих целей?

vga ★★
()
Ответ на: комментарий от vga

Незачто :) Пример работы/использования можно в сорцах Qt посмотреть, в методе сокета bytesAvailable или как-то так

yoghurt ★★★★★
()

> read (pch->sock, buff, BUFFER_LEN)

recv(int sockfd, void *buf, size_t len, int flags);

The flags argument to a recv() call is formed by OR'ing one or more of the following values:

MSG_DONTWAIT (since Linux 2.2)
       Enables nonblocking operation; if the operation would block, the call fails with the
       error EAGAIN or EWOULDBLOCK (this can also be enabled using the O_NONBLOCK flag with
       the F_SETFL fcntl(2)).

не подойдёт?

arsi ★★★★★
()
Ответ на: комментарий от arsi

recv уже тоже попробовал. но какая разница, у меня на сокете уже висит флаг O_NONBLOCK.

Deleted
()
Ответ на: комментарий от arsi

Это ж надо... первый класс, вторая четверть. Прям стыдно даже стало за такой глупый косяк. Ппц. -1 в собственных глазах.

нет слов вобщем. спасиб!

Deleted
()
Ответ на: комментарий от yoghurt

можно в сорцах Qt посмотреть, в методе сокета bytesAvailable

Посмотрел. Лучше бы не смотрел, не ожидал от Qt, они его похоже вызывают в read, то есть вместо одного сискола всегда будет два.

glib как-то обходится без лишних ядерных вызовов, у них FIONREAD только в inotify, но там оно реально нужно, похоже.

vga ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.