Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 500x500-min
operator 4host

В этой статье описывается создание двух простых консольных приложений, одно из которых (intcp) является сервером и получает сооб щения, а другое (outtcp) является клиентом и отправляет сообщение серверу, используя протокол TCP/IP. Сообщения успешно отправляются и принимаются на одном компьютере и на разных компьютерах в одной локальной сети. Взаимодействие этих приложений через интернет автором пока не проверялось.
Приложение Outtcp
Код приложения содержит 3 функции:
1) функция ctime() возвращает текущее время
2) функция main() содержит основной код приложения
3) функция getSocketError() выдает сообщение об ошибке
Функция main()
Приведем полностью код функции main(): 
#pragma argsusedint main(int argc, char argv[]) {  
char clientRequest[REQUEST_MSG_SIZE];  
sockaddr_in serverAddr; //servers socket address  
int sockAddrSize; //size of socket address structure  
SOCKET sHandle; //socket descriptor  
unsigned nbyte; //number of sended bytes  
double starttime, endtime;  
unsigned mlen; //messages length  
char serverName; //servers 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 clients 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; // servers socket address
  sockaddr_in clientAddr; // clients 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.

Возможности нашего Хостинга

Instant Setup

Instant Setup

Выполняется мгновенная настройка хостинга в зависимости от предпочтений клиента, направления работы ресурса, натроек домена.

Instant Backup

Instant Backup

Вы можете не беспокоиться относительно сохранности информации в случае непредвиденного сбоя, отключения.

cPanel Included

cPanel Included

Максимально адаптированная и упрощенная панель позволяет оперативно выполнять настройки и управлять работой на хостинге.

280+ Scripts

280+ Scripts

Вы сможете использовать порядка 280+ скриптов, созданные на высоком уровне специально с целью улучшения работы.

PHP MySQL

PHP & MySQL

Обеспечивается постоянная поддержка расширений стандартов от PHP 4.5 до PHP 7 между MySQL, полноценное взаимодействие между ними.

24/7 Support

24/7 Support

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

Secure Reliable

Secure & Reliable

Внимание уделяется вопросам защиты личных данных, паролей доступа, сохранность конфиденциальной информации о владельце ресурса.

GIT/SVN Support

GIT/SVN Support

Обеспечивается полноценная поддержка пользователей по вопросам перевода данных между системами контроля версий.

Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 01-angular-icon
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 02-css-3
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 03-druplicon-vector
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 06-html-5
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 07-joomla-seeklogo.com
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 08-magento-2
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 09-nodejs-icon
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 11-react
Использование протокола TCP/IP - 4Host: хостинг, домены, реселлерские планы, виртуальные выделенные серверы. Надёжный хостинг в Украине - 12-wordpress-seeklogo.com