• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Вопрос : проблемы при работе сервера по Tcp/ip (Сокеты)

  • Автор темы 4xter
  • Дата начала
4

4xter

Народ, всем доброго дня=) такая проблемка имеется сервак, к которому подключаются клиенты и который обрабатывает набор данных и отправляет клиенту. Так вот всё отрабатывает правильно и рассчитывает всё здорово, но вот сервак постоянно идет по циклу считывания данных с сокета и причем постоянно. В чем беда не могу понять. Очень надеюсь на вашу помощь.
Вот код серкера. Он получает 2 координаты и возвращает номер четверти, в которой расположена точка:
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Сервер"</div></div><div class="sp-body"><div class="sp-content">#include <winsock2.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);
WSAStartup(wVersionRequested,&wsaData);//инициализация WinSock API
//Создание сокета
SOCKET s=socket(AF_INET,SOCK_STREAM,0);
//структура адреса
struct sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port=htons(1280);
local.sin_addr.s_addr=htons(INADDR_ANY); //хранится физический IP
int c=bind(s,(struct sockaddr*)&local,sizeof(local));
//помещает сокет в состояние прослушивания
int r=listen(s,5);
while (true)
{
char b1[255];
//b1 = (char*)malloc(strlen(b1) + 1);
char *b2,*Res,*token,*tmp;
int x,y;
b2 = (char*)malloc(strlen(b1) + 1);
//free(b2);
//Структура определяет удаленный адрес
//с которым соединяется сокет
sockaddr_in remote_addr;
int size=sizeof(remote_addr);
SOCKET s2=accept(s,(struct sockaddr*)&remote_addr,&size);
if (s2 == INVALID_SOCKET)
continue;
cout << "Client connected..." << endl;

while(recv(s2,b1,sizeof(b1),0)!=0)
{
int mas[2],x,y,n=0,res=0;
char cset[] = "1234567890-";
//Разбитие на координаты.
tmp=new char[strlen(b1)];
strcpy(tmp,b1);
token = strtok(tmp,";");
while( token != NULL )
{
int fl=0;
char * pch = token;
if (pch[0]=='-')
fl=1;
while(!isdigit(*pch))
{pch++;}
if (pch!=NULL)
{
if (fl==0)
mas[n]=atoi(pch);
else
mas[n]=atoi(pch)*(-1);
n++;
}
token = strtok( NULL,";");
}
x=mas[0];
y=mas[1];
if ((x>0)&&(y>0))
res=1;
else if ((x<0)&& (y>0))
res=2;
else if ((x<0)&& (y<0))
res=3;
else if ((x>0)&& (y<0))
res=4;
_itoa(res,b2,10);
Res=new char[strlen(b2)+1];
strcpy(Res,b2);
Res[strlen(b2)]='\0';
send(s2,Res,sizeof(Res),0);
cout << "Message sent"<< endl;
}
closesocket(s2);
//delete []Res;
//free(b1);
}

WSACleanup();
return 0;
}
 
L

lazybiz

If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking.

Понимаешь в чем смысл?

Добавлено: Посмотри вот здесь и описание и пример есть:
 
4

4xter

как я понял нужно заблокировать сокет, так?
но у меня не получилось закрыть его. я взял closesocket(s2); перенёс в конец цикла.
 
L

lazybiz

4xter
как я понял нужно заблокировать сокет, так?
Да нет. Я другое имел в виду. Функция recv() не возвращается до тех пор, пока не прочитает что-то из сокета. А когда она что-то прочитывает то возвращаешь значение > 0, т.е. количество прочитанных байт и, соответственно, цикл крутится. Он может прерваться только в том случае если возникнет какая-то ошибка но они, как я понял не возникают. Думаю что все дело в этом. На 100% утверждать конечно не буду, это просто мое предположение.
 
4

4xter

я как-то вообще запутался...вот кусок кода с другой задачи сервера, которая возвращает слово в обратном порядке:
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Сервер2"</div></div><div class="sp-body"><div class="sp-content">while(recv(s2,b1,sizeof(b1),0)!=0)
{
cout << b1 << endl;
int i=strlen(b1);
b2=b1[strlen(b1)];//копируем окончание стоки
i--;
cout <<strlen(b1)<<endl;
for(unsigned j=0;j<=strlen(b1);j++)

{
if (i>=0)
{
b2=b1[j];
i--;
}
}
for(unsigned j=0;j<=strlen(b1);j++)
b1[j]=b2[j];
send(s2,b1,sizeof(b1),0);
cout << "Message sent"<< endl;
}

Подключение к сокету один в один как в предыдущем. Здесь всё Ок и никаких подвисаний не наблюдается. В чём может быть проблема?!
 
4

4xter

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Сервер2 "</div></div><div class="sp-body"><div class="sp-content">#include <winsock2.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);
WSAStartup(wVersionRequested,&wsaData);//инициализация WinSock API
//Создание сокета
SOCKET s=socket(AF_INET,SOCK_STREAM,0);
//структура адреса
struct sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port=htons(1280);
local.sin_addr.s_addr=htons(INADDR_ANY); //хранится физический IP
int c=bind(s,(struct sockaddr*)&local,sizeof(local));
//помещает сокет в состояние прослушивания
int r=listen(s,5);
while (true)
{
char b1[128];
//b1 = (char*)malloc(strlen(b1) + 1);
char *b2;
b2 = (char*)malloc(strlen(b1) + 1);
//free(b2);
//Структура определяет удаленный адрес
//с которым соединяется сокет
sockaddr_in remote_addr;
int size=sizeof(remote_addr);
SOCKET s2=accept(s,(struct sockaddr*)&remote_addr,&size);
if (s2 == INVALID_SOCKET)
continue;
cout << "Client connected..." << endl;

while(recv(s2,b1,sizeof(b1),0)!=0)
{
cout << b1 << endl;
int i=strlen(b1);
b2=b1[strlen(b1)];//копируем окончание стоки
i--;
cout <<strlen(b1)<<endl;
for(unsigned j=0;j<=strlen(b1);j++)

{
if (i>=0)
{
b2=b1[j];
i--;
}
}
for(unsigned j=0;j<=strlen(b1);j++)
b1[j]=b2[j];
send(s2,b1,sizeof(b1),0);
cout << "Message sent"<< endl;
}
closesocket(s2);
}

WSACleanup();
return 0;
}
 
L

lazybiz

Начну пожалуй вот с чего:
C++:
while (true)
{
char b1[128];
//b1 = (char*)malloc(strlen(b1) + 1);
char *b2;
b2 = (char*)malloc(strlen(b1) + 1);
Ты выделяешь память для b2 определяя размер строки b1 которая ни разу не инициализировалась! Т.е. память под b2 может вообще не выделится.

Вот тут тоже какая то странная конструкция:
C++:
int i=strlen(b1);
b2[i]=b1[strlen(b1)];//копируем окончание стоки
Почему бы вторую строку не заменить на: b2=b1; ?

И это я только сразу заметил. Ты бы сначала все ошибки исправил а потом бы мы уже подумали что, почему и как не работает.
 
L

lazybiz

И еще. Когда постишь код вставляй его в тэг C++.
 
4

4xter

мне нужна помощь в выходе из цикла чтения сокета, а не выделения памяти и алгоритма работы сервера... я понимаю что есть ошибки и т.д. но как они влияют на чтение?
 
L

lazybiz

я понимаю что есть ошибки и т.д. но как они влияют на чтение?
Андрей я с Вас фигею.. Возникает ошибка - из-за этого прерывается выполнение recv() а так же прерывается цикл и вы начинаете думать что все работает как надо хотя на самом деле все далеко не так. В общем правьте ошибки.
 
4

4xter

Начну пожалуй вот с чего:
C++:
while (true)
{
char b1[128];
//b1 = (char*)malloc(strlen(b1) + 1);
char *b2;
b2 = (char*)malloc(strlen(b1) + 1);
Ты выделяешь память для b2 определяя размер строки b1 которая ни разу не инициализировалась! Т.е. память под b2 может вообще не выделится.

Вот тут тоже какая то странная конструкция:
C++:
int i=strlen(b1);
b2[i]=b1[strlen(b1)];//копируем окончание стоки
Почему бы вторую строку не заменить на: b2=b1; ?

И это я только сразу заметил. Ты бы сначала все ошибки исправил а потом бы мы уже подумали что, почему и как не работает.


по порядку что поправил: память под b2 выделяется. переменная i мне нужна как обратный счетчик для формирования строки-зеркала. пусть поменяется b2=b1[strlen(b1)] на b2=b1. я так понял что в коде сервер2 где возникает ошибка в b1? так это? Не судите строго, только начинаю всё это осваивать!=)
 
L

lazybiz

Сейчас немного занят на работе. Посмотрю ближе к вечеру.

Добавлено: 4xter
В клиенте, который ты мне прислал есть строки подобные вот этой:
C++:
if ( recv( s, b, sizeof( cool.gif, 0 ) != 0 ) {
Думаю там какой-то символ был распознан как смайл.
Не подскажешь что там должно быть? Или как вариант можно прислать еще раз но только в аську.
 
L

lazybiz

Вот тебе сервер:
C++:
#include <winsock2.h>
#include <iostream.h>

int main( void )
{
WORD		wVersionRequested;
WSADATA		wsaData;

wVersionRequested = MAKEWORD( 2, 2 );
if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
cout << "WSAStartup(): error" << endl;
return 1;
}

SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );

struct sockaddr_in	local;
local.sin_family		= AF_INET;
local.sin_port			= htons( 1280 );
local.sin_addr.s_addr	= htons( INADDR_ANY );

bind( s, (struct sockaddr *)&local, sizeof( local ) );
listen( s, 5 );
while ( 1 ) {
int			size, xy[2], z;
SOCKET		s2;
sockaddr_in	remote_addr;

size = sizeof( remote_addr );

s2 = accept( s, (struct sockaddr *)&remote_addr, &size );
if ( s2 == INVALID_SOCKET ) continue;

cout << "Client connected..." << endl;

while ( recv( s2, (char *)&xy[0], sizeof( int ) * 2, 0 ) != 0 ) {
cout << "Server received: X = " << xy[0] << ", Y = " << xy[1] << endl;
cout.flush();

z = xy[0] * xy[1];	// Schitaem proizvedenie

send( s2, (char *)&z, sizeof( int ), 0 );
}
closesocket( s2 );
}
WSACleanup();
return 0;
}

А вот тебе клиент:
C++:
#include <winsock2.h>
#include <iostream.h>

int main( void )
{
WORD		wVersionRequested;
WSADATA		wsaData;

wVersionRequested = MAKEWORD( 2, 2 );
if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
cout << "WSAStartup(): error" << endl;
return 1;
}

sockaddr_in		peer;
peer.sin_family			= AF_INET;
peer.sin_port			= htons( 1280 );
peer.sin_addr.s_addr	= inet_addr( "127.0.0.1" );

SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
if ( connect( s, (struct sockaddr *)&peer, sizeof( peer ) ) != 0 ) {
cout << "connect(): error" << endl;
return 1;
}

int		xy[2], z;
cout << "Enter X: ", cin >> xy[0];
cout << "Enter Y: ", cin >> xy[1];

send( s, (char *)&xy, sizeof( int ) * 2, 0 );
if ( recv( s, (char *)&z, sizeof( int ), 0 ) != 0 ) {
cout << "Server returns: " << z << endl;
}

closesocket( s );
WSACleanup();
return 0;
}

Сервер получает два числа от клиента и отправляет их произведение обратно клиенту. Заменишь на свою функцию и будет тебе радость.
 
4

4xter

спасибо!!! переработал под свою задачу всё заработало=) по аналогии решил и со строками=)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!