kutuzov |
Отправлено: 09.10.2006, 20:24 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 27
|
Пытаюсь соединится с сервером
ClientSocket1->Host="localhoset";
ClientSocket1->Port=81;
ClientSocket1->Active=true;
получаю следующее:
"Windows socket error: затребованное имя допустимо и оно найдено в базе данных, но для имени отсутсвуют связанные с ним данные, который были разрешены для него(11004), on API 'Asyc Lookup"
Как с этим бороться? |
|
Mystique |
Отправлено: 09.10.2006, 21:08 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 1
|
ClientSocket1->Host="localhoset"
Localhoset это что?? Localhost или 127.0.0.1
так вернее |
|
kutuzov |
Отправлено: 09.10.2006, 21:16 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 27
|
описочка
пофигу что писать пробовал и 127.0.0.1 и масакрадный и внешний IP...
Все до того места на котором сижу |
|
Arsa |
Отправлено: 09.10.2006, 21:27 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 77
|
А сервер на том же порту? Сам писал сервер или апача, или еще что.
И еще, не пойму тех, кто пишет не через винсок! |
|
kutuzov |
Отправлено: 09.10.2006, 21:29 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 27
|
QUOTE (Arsa @ 09.10.2006, 21:27) | А сервер на том же порту? Сам писал сервер или апача, или еще что.
И еще, не пойму тех, кто пишет не через винсок! |
та на том же!!!!
такой же на билдере сервер ...
|
|
kutuzov |
Отправлено: 09.10.2006, 21:32 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 27
|
QUOTE (Arsa @ 09.10.2006, 21:27) | И еще, не пойму тех, кто пишет не через винсок! |
а чем винсок лучше????
|
|
Arsa |
Отправлено: 09.10.2006, 21:46 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 77
|
Ну как тебе сказать? Наверняка, ТСерверсок и тклиентсок написан на винсоке. По-этому, если тебе не интересно знать что да как, так сказать более глубоко, то их вполне достаточно. Я тоже начинал писать с сокетных компонентов, но потом, разобравшись с винсоками и изучив их — даже в мыслях нет кинуть на форму ткиентсокет или т серверсокет.
А по поводу твоей проблемы. Открой брэндмауэр, посмотри включен ли он. Если включен и в списках исключений нет твоего сервера, и при этом когда ты запускаешь сервер не вылазит табло брэндмаура мол кто-то пытется открыть порт, разрешить или блокировать, ТО ДЕЛЕМА В СЕРВАКЕ! |
|
Insert |
Отправлено: 09.10.2006, 23:25 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 2
|
Здраствуйте!
Начал буквально недавно изучать язык С++ ну, а пишу все это дело в С++Builder.
До этого изучал PHP поэтому такой вот вопрос.
Как реализовать следующее:
Отправить POST запрос через сокет.
Перерыл столько уже инфы по ClientSocket. Но не чего разумного так и не нашел. Все опиcание встречающееся обычно ограничесваеться напиcанием на С++ программ клиента и сервера обменивающихся данными между собой! Мне надо чтоб программа обправляла данные на сервер в интернет. Посылая POST(не GET) запрос! и читала ответ в переменную!
На PHP это реализуеться вот так:
CODE |
$url= "http://www.sait.ru/script.php";
//Обрабатываем("парсим") URL1
$url=parse_url($url);
$host=$url['host'];
$path=$url['path'];
//параметр который будет передаваться
$text = "Текст";
$postdata= "parametr1=$text";
$Length = strlen($postdata);
//Открываем сокет
$socket=fsockopen($host,80,$errno,$errstr,60) or die("Can't open socket");
// Заголовок HTTP-запроса
$headers = "POST $path HTTP/1.1\r\n";
$headers .= "Host: $host\r\n";
$headers .= "Content-type: application/x-www-form-urlencoded\r\n";
$headers .= "Content-Length: $Length\r\n\r\n";
// Отправляем HTTP-запрос серверу
fwrite($socket, $headers.$postdata);
//Читаем данные с сервера
while(!feof($socket))
{
$page .= fgets($socket);
}
//закрываем сокет
fclose($socket);
//ответ сервера в переменной $page
...
//выходим
exit;
|
Ну вот как нечто подобное в "С++" реализовать с помощью компонента "ClientSocket" или может есть какой то другой более
подходящий для работы с сокетами!
Желательно поподробнее! и со всеми нюансами!
Пока мне удаеться только установить соединение.
Отправить POST запрос и получить ответ сервера мне не удаеться!
Надеюсь на вашу помощь!
Заранее спасибо!
|
|
Arsa |
Отправлено: 10.10.2006, 07:02 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 77
|
QUOTE | Желательно поподробнее! и со всеми нюансами!
|
CODE |
AnsiString query = "POST http://www.cbuilder.ru/ HTTP/1.0\r\nAccept: */*\r\nReferer: \r\nAccept-Language: en \r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\nConnection: Keep-Alive\r\n\r\n";
WSADATA lpWSAData;
SOCKET s;
// Инициализация библиотеки Ws2_32.dll.
if (WSAStartup(MAKEWORD(2,2),&lpWSAData)!=0){
ShowMessage("Не могу подгрузить библиотеку \"Ws2_32.dll\"");
return;
}
s=socket(AF_INET, SOCK_STREAM, 0);
if (s==INVALID_SOCKET){
ShowMessage("Не могу создать объект \"Socket\"");
return;
}
//разбиваем ип на 4 части
struct hostent* hp;
hp=gethostbyname("www.cbuilder.ru");
// Заполняем структуру sockaddr_in
struct sockaddr_in ssin;
memset ((char *)&ssin, 0, sizeof(ssin));
ssin.sin_family = AF_INET;
ssin.sin_addr.S_un.S_un_b.s_b1 = hp->h_addr[0];
ssin.sin_addr.S_un.S_un_b.s_b2 = hp->h_addr[1];
ssin.sin_addr.S_un.S_un_b.s_b3 = hp->h_addr[2];
ssin.sin_addr.S_un.S_un_b.s_b4 = hp->h_addr[3];
ssin.sin_port = htons(80);
// Соединяемся с хостом
if(connect(s, (sockaddr *)&ssin, sizeof(ssin))==-1){
ShowMessage("Не могу соединиться");
return;
}
// Отправляем запрос серверу
int cnt=send(s,query.c_str(),query.Length(), MSG_DONTROUTE);
// Проверяем, не произошло ли ошибки при отправке запроса на сервер
if (cnt==SOCKET_ERROR){
ShowMessage("Ошибка при отправке!");
return;
}
// Получаем ответ с сервера ---------------------------------
int rr=1;
char result_ptr[1000000];
AnsiString ares = "";
do{
rr = recv(s, result_ptr, sizeof(result_ptr),0);
if(rr > 0){
ares = (ares+ result_ptr).c_str();
}
free(result_ptr);
}while(rr > 0);
free(result_ptr);
ShowMessage("Получен ответ:\r\n"+ares+"\r\n");
if(rr == SOCKET_ERROR) {
ShowMessage("Произошла ошибка при получении ответа\r\n");
return;
}
//Деинициализация библиотеки Ws2_32.dll
WSACleanup();
|
#include не забудь подключить
Удачи! |
|
Arsa |
Отправлено: 10.10.2006, 07:05 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 77
|
CODE | #include <winsock.h> | |
|
Insert |
Отправлено: 10.10.2006, 14:35 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 2
|
QUOTE | Arsa написал:
... очень подробное руководство ... |
Arsa БОЛЬШОЕ СПАСИБО! ВСЕ ВЕЛИКОЛЕПНО РАБОТАЕТ!
Ответ от сервера получаю! Очень сильно помог!
Правдо пришлось повозиться с тем чтобы передать переменные
скрипту. Но все таки мне это удолось, пришлось почитать вообще о методах передачи браузером HTTP запросов.
Вообщем если кому то пригодиться то вместо строки:
Arsa написал:
CODE |
AnsiString query = "POST [URL=http://www.cbuilder.ru/]http://www.cbuilder.ru/[/URL] HTTP/1.0\r\nAccept: */*\r\nReferer: \r\nAccept-Language: en \r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\nConnection: Keep-Alive\r\n\r\n";
WSADATA lpWSAData;
|
приведенной в листенге выше.
Заменить чем то вроде этого:
CODE |
//вводим передаваемые данные
AnsiString parametr = "name=ivan&password=12345";
AnsiString len_parametr = parametr.Length();
//формируем запрос
AnsiString query = "POST ";
query += "http://www.mysyte.ru/script.php";//можно получить из Edit
query += " HTTP/1.0\r\nAccept: */*\r\n";
query += "Referer: \r\nAccept-Language: en \r\n";
query += "Content-Type: application/x-www-form-urlencoded\r\n";
query += "Content-Length: " + len_parametr + "\r\n";
query += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n\r\n";
query += parametr;
|
В результате переменным "name" и "password" скрипта "script.php" будут переданны значения "ivan" и "12345"
Ну и здесь:
Arsa написал:
CODE |
hp=gethostbyname("www.cbuilder.ru");
|
заменить "www.cbuilder.ru" на "www.mysyte.ru"
...
Arsa тогда сразу еще очень интересующий вопрос, да и для дальнейшего развития темы. А как ограничеться приемом только вот этой части ответа сервера:
CODE |
HTTP/1.1 200 OK
Date: Tue, 10 Oct 2006 09:26:05 GMT
Server: Apache/2.0.55 (Win32) PHP/5.1.3
X-Powered-By: PHP/5.1.3
Content-Length: 423
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html
|
Без HTML текста. Это вообще возможно сделать?
Отредактировано Insert — 10.10.2006, 15:52 |
|
Arsa |
Отправлено: 10.10.2006, 14:49 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 77
|
Насчет ограничиться не знаю, но ответ можно обрезать для обработки:
ansistring xxx = ares.substring(1, ares.pos("\r\n\r\n") — в итоге получишь "шапку" запроса |
|
Arsa |
Отправлено: 10.10.2006, 14:55 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 77
|
Ну а вообще, коль тебя тема сокетов интересует, то почитай, то что мне очень когда-то помогло:
Приложение Outtcp
Код приложения содержит 3 функции:
1) функция ctime() возвращает текущее время
2) функция main() содержит основной код приложения
3) функция getSocketError() выдает сообщение об ошибке
Функция main()
Приведем полностью код функции main():
#pragma argsused
int main(int argc, char* argv[]) {
char clientRequest[REQUEST_MSG_SIZE];
sockaddr_in serverAddr; //server's socket address
int sockAddrSize; //size of socket address structure
SOCKET sHandle; //socket descriptor
unsigned nbyte; //number of sended bytes
double starttime, endtime;
unsigned mlen; //message's length
char* serverName; //server's name
WSADATA wsaData; //data structure that is to receive
//details of the Windows Sockets
//implementation
Здесь мы объявляем переменные, используемые функцией.
serverName = argv[1];
В этой строке мы присваиваем серверу имя, которое представляет собой IP-адрес, полученный в качестве параметра при запуске программы. Если программа будет запущена без параметров, возникнет ошибка. При наличии более одного параметра, остальные параметры будут проигнорированы. Если оба приложения (outtcp и intcp) будут запускаться на одном компьютере, то в качестве имени сервера следует указывать 127.0.0.1
//initiate use of WS2_32.DLL by a process
if(WSAStartup(MAKEWORD(1, 1), &wsaData)) {
getSocketError();
getch();
return 0;
}
Функция WSAStartup() должна быть вызвана в первую очередь любым приложением или библиотекой DLL, которые используют сокеты. В качестве первого параметра указывается версия Windows Sockets, которую может использовать вызывающая программа. При успешном завершении этой функции структура wsaData заполняется информацией, характеризующей данную реализацию Windows Sockets.
//create client's socket
if((sHandle = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
getSocketError();
getch();
return 0;
}
Здесь мы создаем сокет с помощью функции socket(). Первый параметр этой функции — формат, в котором будет задан адрес, а второй параметр — тип создаваемого сокета. Для версии Windows Sockets 1.1 можно указывать только один из двух типов: SOCK_STREAM (создается двунаправленный поток байтов, используется протокол TCP) или SOCK_DGRAM (поддерживает передачу дейтаграмм, используется протокол UDP). С помощью третьего параметра можно указать протокол, используемый сокетом.
// build server socket address
sockAddrSize = sizeof(sockaddr_in);
memset(&serverAddr, 0, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT_NUM);
Константа SERVER_PORT_NUM не является библиотечной и была определена нами в файле tcp.h.
if((serverAddr.sin_addr.s_addr = inet_addr(serverName))
== INADDR_NONE)
{
perror("unknown server name");
closesocket(sHandle);
getch();
return 0;
}
Здесь мы преобразуем полученный в качестве параметра при запуске программы адрес (который пока представлен в виде строки) в формат, соответствующий протоколу. Если адрес является недействительным, функция inet_addr() возвращает INADDR_NONE.
//connect to server
if(connect(sHandle, (sockaddr *)&serverAddr,
sockAddrSize) == -1)
{
getSocketError();
closesocket(sHandle);
getch();
return 0;
}
Функция connect() получает в качестве параметров дескриптор сокета, адрес структуры, содержащей информацию об адресе сервера, и размер этой структуры.
//fill string to send
printf("Introduce the string to send:\n");
gets(clientRequest);
mlen = strlen(clientRequest);
if(mlen>= REQUEST_MSG_SIZE) {
printf("Max length of message is %d bytes !\n",
REQUEST_MSG_SIZE-1);
getch();
return 0;
}
Запрашиваем у пользователя ввод строки, которую нужно передать серверу.
//send request to server
starttime = ctime();
if((nbyte = send(sHandle, (char *)clientRequest,
mlen, MSG_DONTROUTE)) == SOCKET_ERROR)
{
getSocketError();
closesocket(sHandle);
getch();
return 0;
}
Отправляем серверу введенную пользователем строку. Функция send() возвращает количество переданных байт или значение SOCKET_ERROR при неуспешном завершении.
if(nbyte != mlen)
printf("Write only %d (%d) bytes\n", nbyte, mlen);
endtime = ctime() — starttime;
printf("send_time = %f\n", (float)endtime);
closesocket(sHandle);
Выводим время, затраченное на пересылку данных и закрываем сокет с помощью функции closesocket().
printf("Press any key\n");
getch();
return 0;
}
Функция getSocketError()
void getSocketError() {
LPVOID lpMsgBuf;
if (!FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL ))
{
MessageBox(NULL, "Error number not found",
"Error", MB_OK | MB_ICONSTOP );
return;
}
// Display the string.
MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error",
MB_OK | MB_ICONSTOP);
// Free the buffer.
LocalFree(lpMsgBuf);
}
Функция getSocketError() выводит диалоговое окно с сообщением об ошибке. Текст сообщения мы получаем с помощью функции FormatMessage(), которая анализирует код ошибки, возвращаемый функцией Windows API GetLastError().
Приложение intcp
Код серверного приложения intcp содержит функции main() и getSocketError().
Функция main()
int main() {
sockaddr_in serverAddr; // server's socket address
sockaddr_in clientAddr; // client's socket address
int sockAddrSize; // size of socket address structure
SOCKET sHandle; // socket file descriptor
SOCKET newSHandle; // socket descriptor from accept
WSADATA wsaData; //data structure that is to receive details
//of the Windows Sockets implementation
int nbyte = 0; //number of sended bytes
char clientRequest[REQUEST_MSG_SIZE];
// set up the local address
sockAddrSize = sizeof(sockaddr_in);
memset(&serverAddr, 0, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT_NUM);
serverAddr.sin_addr.s_addr = INADDR_ANY;
Структура serverAddr заполняется почти так же, как и в предыдущем приложении, но полю serverAddr.sin_addr.s_addr присваивается значение INADDR_ANY. Это означает, что IP-адрес клиента заранее не определен.
// initiate use of WS2_32.DLL by a process
if(WSAStartup(MAKEWORD(1, 1), &wsaData)) {
getSocketError();
getch();
return 0;
}
// create a TCP-based socket
if((sHandle = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
getSocketError();
getch();
return 0;
}
// bind socket to local address
if(bind(sHandle, (sockaddr *)&serverAddr,
sockAddrSize) == -1 )
{
getSocketError();
closesocket(sHandle);
getch();
return 0;
}
Использование функций WSAStartup() и socket() аналогично предыдущему приложению. После удачного завершения функции socket() мы вызываем функцию bind(), которая связывает локальный адрес с сокетом.
// create queue for client connection requests
if(listen(sHandle, SERVER_MAX_CONNECTIONS) == -1) {
getSocketError();
closesocket(sHandle);
getch();
return 0;
}
Функция listen() переводит сокет в состояние ожидания запросов от клиентов. Эту функцию следует использовать для сокетов типа SOCK_STREAM. Функция listen() обычно используется серверными приложениями.
// accept new connect requests and spawn tasks to process them
// Note: newSHandle socket will take propreties of
// sHandle socket
if((newSHandle = accept(sHandle, (sockaddr *)&clientAddr,
&sockAddrSize)) == INVALID_SOCKET)
{
getSocketError();
closesocket(sHandle);
getch();
return 0;
}
Функция accept() извлекает из очереди запросов первый запрос для данного сокета, затем создает новый сокет, который и должен обработать этот запрос. Созданный сокет обладает точно такими же свойствами, что и первоначальный сокет, дескриптор которого передается функции в качестве первого параметра. При успешном завершении функция accept() возвращает дескриптор нового сокета.
nbyte = recv(newSHandle, (char *)clientRequest,
sizeof(clientRequest), MSG_PEEK);
if (nbyte != SOCKET_ERROR) {
printf("Have received %d bytes \n", nbyte);
printf("Data: %s\n", clientRequest);
}
else
getSocketError();
Здесь мы получаем сообщение от клиента с помощью функции recv(). Если четвертый параметр функции имеет значение MSG_PEEK, это означает, что функция будет считывать входящие данные. При этом данные копируются в буфер clientRequest (второй параметр), но не удаляются из очереди входящих данных. Если функция завершается удачно, то возвращаемое значение равно количеству полученных байт. В противном случае возвращается SOCKET_ERROR.
memset(clientRequest, 0, REQUEST_MSG_SIZE);
closesocket(sHandle);
closesocket(newSHandle);
printf("Press any key\n");
getch();
return 0;
}
Примечание: сначала следует запускать intcp. В противном случае при запуске outtcp будет выдано сообщение об ошибке: "Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение". После запуска intcp запустите outtcp (указав адрес сервера), введите строку, которая будет передана приложению intcp и нажмите Enter. Строка будет выведена в окне приложения intcp.
|
|
|