Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » C/С++ : Сокеты

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

Octane

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Очень хотелось бы узнать как реализуется работа с сокетами в C/C++
Интересует:
 -подключение
 -отправление запроса
 -получение ответа
 -ожидание подключения/запроса
 
примеры приветствуются

Всего записей: 130 | Зарегистр. 30-11-2002 | Отправлено: 03:27 15-01-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
В каком смысле - как реализуется? Ты про специальные библиотеки? или про Berkley Sockets для С?
Какаие реализации ты знаешь?

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 15:06 15-01-2003
Octane

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
никакие не знаю потому и спрашиваю как реализовать то что я написал...

Всего записей: 130 | Зарегистр. 30-11-2002 | Отправлено: 16:28 15-01-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Там вся работа делится на две части - клиентскую и серверную.
Клиентская - попроще. Расскажу на примере виндов, подробности по применению функций - в MSDN.
 
сначала включаешь header  
#include <winsock.h>
 
далее инициализируешь посистему Windows Sockets (в UNIX этого делать не надо)
// что-то типа  
WSAStartup(...);
 
Затем создаешь сокет
SOCKET sock = socket(AF_INET, SOCK_STREAM, ...) //Это для TCP
 
Дальше идет шаманство с колучение интернет представления для IP-адреса сервера, приведу нужные функции
gethostbyname(...)
inet_addr(...)
getprotobyname(...)
ntohl(...), htonl(...)
ntohs(...), htons(...)
 
Когда получишь адрес в СЕТЕВОМ виде, можешь цепляться к серверу функцией
connect(sock,...)
 
дальше - передача пакетов на сервер - функцией send, прием - функцией recv.
 
закрываешь сокет:
сначала shutdown(sock, mode); // В большинстве случаев вешь нужная - сбрасывает все не переданные буфера
затем closesocket(sock); // В UNIX - это просто close(sock);
 
Ну и в конце деинициализация Windows Sockets:
WSACleanup(...)
 
Примеры - весчь долгая и нудная. Если очень надо - напишу из работающего, а проще - в Internet поискать

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 07:58 16-01-2003
Octane

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Если не сложно дайте исходник проги типа скажем коннект к 127.0.01:80 запрос www-странички , вывод на экран ответа...

Всего записей: 130 | Зарегистр. 30-11-2002 | Отправлено: 14:38 19-01-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Mickey_from_nsk
давай

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 02:11 20-01-2003
Serjik



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Пример, отправка почты:
 

Код:
void CTest_sockDlg::WaitFor(char ResponseCode[])
{
int retval;
char Buffer[100]="";
while(TRUE){
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);
if(strstr(Buffer,ResponseCode) > 0) break;
};
}
 
void CTest_sockDlg::SendBuffer(char sendBuffer[])
{
int retval;
retval = send(conn_socket, sendBuffer, 15, MSG_DONTROUTE);
}
 
int CTest_sockDlg::sendMail()
{
WORD wVersionRequested;
WSADATA wsaData;
struct hostent *hp;
struct sockaddr_in server;
char *server_name = "your server";
int socket_type = SOCK_STREAM;
unsigned short port = 25;
int err;
int retval;
char Buffer[128]="";
 
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup(wVersionRequested, &wsaData);
if (err == SOCKET_ERROR) {
WSACleanup();
exit(-1);
};
hp = gethostbyname(server_name);
if (hp == NULL ) {
WSACleanup();
exit(-1);
};
memset(&server,0,sizeof(server));
memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET,socket_type,0);
if (conn_socket < 0 ) {
WSACleanup();
exit(-1);
}
if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server)) == SOCKET_ERROR) {
WSACleanup();
exit(-1);
}
 
WaitFor("220");
 
SendBuffer("ehlo test.net\n");
WaitFor("250");
 
SendBuffer("mail from: aaa@domain.com\n");
WaitFor("250");
 
SendBuffer("rcpt to: xyz@domain.ru.com\n");
WaitFor("250");
 
SendBuffer("data\n");
WaitFor("354");
 
SendBuffer("From: My_name\n");
SendBuffer("X-Mailer: Simple mailer v.1.0\n");
SendBuffer("To: XYZ_name\n");
SendBuffer("Subject: testing message\n\n");
SendBuffer("This is the body of testing message\n.\n");
WaitFor("250");
 
SendBuffer("quit\n");
WaitFor("221");
 
closesocket(conn_socket);
WSACleanup( );
}

 
что-то вроде...

Всего записей: 471 | Зарегистр. 03-08-2002 | Отправлено: 04:09 20-01-2003 | Исправлено: Serjik, 04:23 20-01-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
zam
Чего давать то ?

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 08:50 20-01-2003
Octane

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Serjik
вот спасибо , теперь будем разбираться ху из что
Mickey_from_nsk
давай делай то , что я попросил
 

Всего записей: 130 | Зарегистр. 30-11-2002 | Отправлено: 13:11 20-01-2003
Serjik



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Octane
сегодня накатал ActiveX/MTS для отправки мыла, работает,
если есть интерес кидай запрос на мыло, или аську...

Всего записей: 471 | Зарегистр. 03-08-2002 | Отправлено: 13:16 20-01-2003 | Исправлено: Serjik, 13:19 20-01-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Mickey_from_nsk
Если не сложно дайте исходник проги типа скажем коннект к 127.0.01:80 запрос www- странички , вывод на экран ответа...
 
Вот этого... можно примеры работы прог такого класса, но на си и без всяких ООП со всеми вытекающими?

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 21:55 21-01-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
zam
Вообще то я привык общаться на ты.
Если немного подождешь (день - два) - немного найду времени и напишу такую штуку. Сейчас времени маловато.
 
Мдааа. Провокационные ты задачи ставишь. Все отложил и написал.
Лови, незабудь при сборке подключить библиотеку ws2_32.lib (Для visual studio).
----------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <WinSock2.h>
 
#define CHECK_URL(x,y) if (x) {fprintf(stderr, ToConsole(y)); return NULL;}
 
struct sockaddr_in sa;
char buf[1024];// Для простоты - фиксируем размер буфера для адреса
 
 
char conBuf[1024];// Буфер для конвертации консольных сообщений
char* ToConsole(char* str)
{
CharToOem(str, conBuf);
return conBuf;
}
 
char* parseURL(char* _url)
{
// Проверяем входной протокол
char *ptr = strchr(_url, ':');
CHECK_URL(ptr == NULL, "Имя протокола отсутствует.\n");
 
*ptr = '\0';
CHECK_URL(stricmp(_url, "http") != 0, "Недопустимое имя протокола.\n");
CHECK_URL(strncmp(++ptr, "//", 2) != 0, "Неправильный формат URL.\n");
 
ptr+=2;
char* eptr = strchr(ptr, '/');
CHECK_URL(eptr == NULL, "Нет имени страницы");
strcat(buf, eptr+1);
 
*eptr = '\0';
eptr = strchr(ptr, ':');
if (eptr != NULL)  
{
char* leptr;
short port = (short)strtol(eptr+1,&leptr, 10);
if (eptr == leptr) port = 80;//Тут можно выдать ошибку насчет неверного порта
*eptr = '\0';
sa.sin_port = htons(port);
}
else
sa.sin_port = htons(80);
 
struct hostent *he = gethostbyname(ptr);
if (he == NULL)
{
he = gethostbyaddr(ptr, strlen(ptr), AF_INET);
CHECK_URL(he == NULL, "Недопустимое имя сервера");
}
memcpy(&sa.sin_addr.S_un.S_addr, he->h_addr, sizeof(sa.sin_addr.S_un.S_addr));
return buf;
}
 
void main(int argc, char**argv)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
 
wVersionRequested = MAKEWORD( 1, 1 );
 
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )  
{
fprintf(stderr, ToConsole("Невозможно инициализировать Windows Sockets.\n"));
return;
}
 
// Проверяем запрошенную версию Windows sockets
if ( LOBYTE( wsaData.wVersion ) != 1 ||HIBYTE( wsaData.wVersion ) != 1 )  
{
fprintf(stderr, ToConsole("Максимально доступная версия Windows Sockets : %d.%d - недопустима."),  
(int)(LOBYTE( wsaData.wVersion )),(int)(HIBYTE( wsaData.wVersion )));
WSACleanup( );
return;  
}
 
// Windows Sockets инициализирована
struct protoent *pe = getprotobyname("tcp");// Запрашиваем идентификатор протокола
SOCKET sock = socket(AF_INET, SOCK_STREAM, pe->p_proto);// Создаем сокет
 
strcpy(buf, "GET /");
// Обрабатываем адрес. Допустимые форматы:
// http://hostname:port/URL
// http://hostname/URL - по умолчанию - 80 порт
if (argc >= 2)// Есть входной параметр
{
if (parseURL(argv[1]) == NULL)  
{ closesocket(sock); WSACleanup(); return; }
}
else
parseURL("http://localhost:80/index.html");
strcat(buf, " HTTP/1.0\n\n");
 
sa.sin_family = AF_INET;
memset(&sa.sin_zero, 0, sizeof(sa.sin_zero));
if (connect( sock, (struct sockaddr*)(&sa), sizeof(sa)) != 0)
{
fprintf(stderr, ToConsole("Ошибка при подключении №%d\n"), WSAGetLastError());
closesocket(sock); WSACleanup(); return;
}
 
//Посылаем запрос на извлечение страницы
send(sock, buf, strlen(buf), 0);
char recvbuf[1024];
int received = 0;
while((received = recv(sock,recvbuf, sizeof(recvbuf)-1,0)) > 0)
{
recvbuf[received] = '\0';
fprintf(stdout, recvbuf);
}
closesocket(sock);
WSACleanup();
}
-------------------------------------------------

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 07:29 22-01-2003 | Исправлено: Mickey_from_nsk, 09:02 22-01-2003
Serjik



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Mickey_from_nsk

Цитата:
//Посылаем запрос на извлечение страницы  
send(sock, buf, strlen(buf), 0);  
char recvbuf[1024];  
int received = 0;  
while((received = recv(sock,recvbuf, sizeof(recvbuf)-1,0)) > 0)  
{  

данные будут читаться, пока не закончатся, а как только закончаться, RECV будет ждать, пока они снова появятся на сокете.
Надо прописать проверку, на наличие входящих данных.
 
Вопрос: как это сделать?  
 
PS. Пошукал сеть, есть какие-то примеры на основе SELECT, попробывал, ничего толкового не получается.

Всего записей: 471 | Зарегистр. 03-08-2002 | Отправлено: 13:43 24-01-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Serjik
Так попробуй прочитать что-нибудь по HTTP-протоколу, хотя бы FTM.
Когда данные на сервере заканчиваются - соединение разрывается СЕРВЕРОМ. При этом recv возвращает то ли отрицательное значение, то ли ноль - не помню точно. А на этот случай - проверка есть.
Если надо писать не HTTP - так и надо говорить.

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 14:30 27-01-2003
vlish

Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Mickey_from_nsk
All

Цитата:
Когда данные на сервере заканчиваются - соединение разрывается СЕРВЕРОМ. При этом recv возвращает то ли отрицательное значение, то ли ноль - не помню точно.  

ноль
 

Всего записей: 71 | Зарегистр. 30-03-2002 | Отправлено: 23:50 27-01-2003
Serjik



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Mickey_from_nsk

Цитата:
Когда данные на сервере заканчиваются - соединение разрывается СЕРВЕРОМ

Я имел ввиду SMTP или POP3 или IMAP, в общем почтовые серваки. Так вот, ответ от сервера может вернуться в несколько приемов, т.е. необходимо несколько раз вызывать RECV, но если вызывешь RECV и в буфере не будет данных, то программа заблокируется, и будет ждать прихода данных, поэтому надо проверять наличие данных в буфере.

Всего записей: 471 | Зарегистр. 03-08-2002 | Отправлено: 02:44 28-01-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я такие вещи делал через второй поток. Запускаешь его и пусть себе висит. Хотя Microsoft byt рекомендует этого делать с весьма интересной формулировкой - что то вроде "каждый поток требует дополнительных расходов памяти", поэтому рекомендуют пользоваться асинхронными вызовами. Мне лениво точно разбираться в этом. Примерно это так. Запускаешь вызов WSARecv()  или что-то похожее, в асинхронном режиме, ей передаешь, каким образом сообщить о приходе данных, затем просто одним из стандартных механизмов ловишь эти данные.

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 08:51 28-01-2003
roma



skydiver
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
я терпеть ненавижу си и неумею его.
но сложилась ситуация при которой мне необходимо чтобы пример с отправкой почты приведённый здесь заработал.
коротко опишу ситацию: ос юникс солярис (это я к тому что наверно мне не нужно будет длл для вин32 и т.п. может ещё какие особенности есть), компилятор gcc компилить собираюсь gcc имяфайла -lnsl -lsocket помоему это соляриса чтоли особенности. вполне естественно что пример приведённый здесь неработает не могли бы вы подсказать чего делать?
Код:
void CTest_sockDlg::WaitFor(char ResponseCode[])
{
int retval;
char Buffer[100]="";
while(TRUE){
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);
if(strstr(Buffer,ResponseCode) > 0) break;
};
}
 
void CTest_sockDlg::SendBuffer(char sendBuffer[])
{
int retval;
retval = send(conn_socket, sendBuffer, 15, MSG_DONTROUTE);
}
 
int CTest_sockDlg::sendMail()
{
WORD wVersionRequested;
WSADATA wsaData;
struct hostent *hp;
struct sockaddr_in server;
char *server_name = "your server";
int socket_type = SOCK_STREAM;
unsigned short port = 25;
int err;
int retval;
char Buffer[128]="";
 
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup(wVersionRequested, &wsaData);
if (err == SOCKET_ERROR) {
WSACleanup();
exit(-1);
};
hp = gethostbyname(server_name);
if (hp == NULL ) {
WSACleanup();
exit(-1);
};
memset(&server,0,sizeof(server));
memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET,socket_type,0);
if (conn_socket < 0 ) {
WSACleanup();
exit(-1);
}
if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server)) == SOCKET_ERROR) {
WSACleanup();
exit(-1);
}
 
WaitFor("220");
 
SendBuffer("ehlo test.net\n");
WaitFor("250");
 
SendBuffer("mail from: aaa@domain.com\n");
WaitFor("250");
 
SendBuffer("rcpt to: xyz@domain.ru.com\n");
WaitFor("250");
 
SendBuffer("data\n");
WaitFor("354");
 
SendBuffer("From: My_name\n");
SendBuffer("X-Mailer: Simple mailer v.1.0\n");
SendBuffer("To: XYZ_name\n");
SendBuffer("Subject: testing message\n\n");
SendBuffer("This is the body of testing message\n.\n");
WaitFor("250");
 
SendBuffer("quit\n");
WaitFor("221");
 
closesocket(conn_socket);
WSACleanup( );
}

 
начиная с инклюдов и т.п.?

----------
ну и на кой мне эта подпись?

Всего записей: 2908 | Зарегистр. 10-09-2001 | Отправлено: 19:43 20-02-2006
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Дааа, тяжелое детство, деревянные игрушки ...
Если хочешь дельного совета, не обязательно хаять язык на котором надо писать.
 
Теперь к делу.
Все инклюдники собирать лениво. Как минимум надо  
<sys/socket.h>
<sys/types.h>
Надо кое что еще, если хочешь работать с разрешением имен. Подробнее - RTFM. Там все очень подробно разжевано.
 
По поводу кода.
В нем достаточно много виндовых заморочек. Заменяй все TRUE на true (если пишешь на C++, а кусок кода явно на нем). Убирай все что связано с WSA, в т.ч. и WORD wVersionRequested.
Или переопредели  
#define SOCKET_ERROR -1
или вообще используй -1 вместо этого.
Немного странноватая функция WaitFor. Можно привести ряд примеров, когда функция strstr в ней не будет работать.
 
Вроде бы так. Народ поправит, если я где-то неправ или что-то пропустил.
Новый код писать лениво.

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 07:11 21-02-2006
roma



skydiver
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
я си не хаю. я выражаю свою жизненную позицию по отношению к нему.

Цитата:
Все инклюдники собирать лениво.

Цитата:
Новый код писать лениво.
если тебе лениво ты непиши ничё, ладно? я не тороплюсь и подожду тех кому не лениво.

----------
ну и на кой мне эта подпись?

Всего записей: 2908 | Зарегистр. 10-09-2001 | Отправлено: 08:52 21-02-2006
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » C/С++ : Сокеты


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru