LINUX.ORG.RU

Господа, помогите! Вопрос по сокетам ...


0

0

Доброго всем времени суток! Я пишу небольшую клиент-сервер пару. В сокетах, тем более на *nix я чайник, поэтому буду благодарен Вам за помощь!

Ситуация: Соединение клиента с сервером происходит нормально. Сервер акцептирует соединение. Потом задача такова: клиент шлет серверу строку данных. Сервер получает ее, обрабатывает и отсылает клиенту ответ в виде тоже строки данных.

Вот в чем проблема: Сервер получает данные от клиента, а потом то ли не отдает, то ли клиент их не получает. В общем оба виснут. Пока еще сервер ничего не делает со строкой от клиента - тест пока только соединения. Т.е. должен пройти хотя бы диалог. А он не получается. Помогите, пожалуйста!

Привожу части программ: Сервер:

char* query = (char*)malloc(128*sizeof(char)); int rc; char c; int n = 0; while(1){ if ( (rc = recv(newsockfd, &c, 1,0)) == 1){ *query++ = c; n++; } else if (rc == 0) break; }; *query = 0; query -= n; printf("HIT: %s\n",query);

char* msg = "Hello, boy!"; send(newsockfd,msg,strlen(msg),0);

Клиент:

send(sockfd,"Hi, man!",strlen("Hi, man!"),0);

int rc; char c; while(1) { if ( (rc = recv(sockfd, &c, 1,0)) == 1){ putc(c,stdout); if(c == 0) break; } // Ответ сервера выводится в stdout else if (rc == 0) break; };

Сокет в обеих прогах открывается так: socket(AF_INET, SOCK_STREAM, 0);

Причем, что странно: когда я убираю второе сообщение. Т.е. либо если оставить только сообщение от клиента серверу, или от сервера клиенту - т.е. одностороннее - все работает. А двустороннее - виснет ...

anonymous

Проблема в while(1)

Принимать данные стоит только когда они есть в буфере, т.е. делать
fd_set rfds;
struct timeval tv;
while (1) {
FD_ZERO(&fds);
FD_SET(newsockfd, &fds);
tv.tv_sec = 10; // типа тайм-аут 10 секунд
select (newsockfd, &fds, NULL, NULL, &tv) ; // далее по параметрам читаем man select
if (FD_ISSET(newsockfd, &fds)) {
   // читаем, причем желательно сразу несколько символов в буфер
   // если что-то получили требуемое, можно и отослать
}
else {
   // нифига не пришло за 10 секунд (см. tv), типа тут можно и break
}
}

Ну и так далее

anonymous
()

Ошибся я с заглавной фразой. Проблема не в while(1), а в том, что read блокируется, если в сокете нет данных.

anonymous
()

А разве read не разблокируется как только данные поступают в сокет? А они вроде должны туда поступить ... Если не затруднит, разъясните, пожалуйста, более подробно. Вообще насколько быстродейственны сокеты ? - у меня планируется до 100 запросов от клиента к серверу в секунду. Спасибо.

anonymous
()

> А разве read не разблокируется как только данные поступают в сокет?

Разблокируется.

> А они вроде должны туда поступить ...
> Если не затруднит, разъясните, пожалуйста, более подробно.

В приведенном примере данные читаются в цикле (процитирую):

while(1) {
if ( (rc = recv(newsockfd, &c, 1,0)) == 1) {
*query++ = c; n++;
} else
if (rc == 0) break;
};
В данном случае данные читаются до упора (read возвратит 0 в случае дисконнекта),
Т.е. пока сокет приконнекчен, read будет либо ждать данные (блокируется),
либо вернет 1, когда данные появятся и он их прочтет.
Так понятнее? Теперь смотри мой первый пост с примером, где применяется select.


>Вообще насколько
>быстродейственны сокеты ? - у меня планируется до 100 запросов от клиента к серверу в
>секунду. Спасибо.

Смотря для чего. Для 100 запросов в секунду сокетов должно хватить.
Конечно, в зависимости от характера запросов.
Делим пропускную способность 10 Мбит ~900Kb/s (реально) на 100, получаем
размер запроса/ответа 9К.
Для 100 Мбит побольше будет (~3-6 Мбайт/с) : ~ 31-62 Кб на ответ/запрос.

anonymous
()

Все равно что-то странное. Сейчас я вообще все лишнее убрал. И не работает. Виснет, а точнее переходит к "нифига не пришло". Почему интересно, когда сервер ясно ему шлет ... Может я что-то пропустил?

Server:

listen(sockfd, 5);

	for( ; ; ) {
		
		clilen = sizeof(cli_addr);
		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen);
    		
		if(newsockfd < 0 ){
			perror("server : accept error");		
		} else {
			
			// по получении соединения, сервер шлет приветствие
				char* msg = "HELLO, BOY!";
				send(newsockfd,msg,strlen(msg),0);


		
		};
		
		close(newsockfd);				
	}


Client:


if(connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) exiterr(1);  // Соединение с сервером


// по соединении с сервером ждем приветствия сервера
	int rc;
       
	fd_set fds;
	struct timeval tv;
	char c;

	while(1)
	{
		FD_ZERO(&fds);
		FD_SET(sockfd, &fds);
		tv.tv_sec = 10; 
	
		select (sockfd, &fds, NULL, NULL, &tv) ; // далее по параметрам читаем man select
		if (FD_ISSET(sockfd, &fds)) {
   				printf("OK"); break;
			if ( (rc = recv(sockfd, &c, 1,0)) == 1){ putc(c,stdout); } // Вывод данных в stdin
				else if (rc == 0) break;

		} else {
   				// нифига не пришло за 10 секунд (см. tv), типа тут можно и break


				printf("NO"); break;
		};

	};
	
	close(sockfd);

anonymous
()

Спасибо за ответы - разобрался. Последний вопрос снимается.

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