Вариант 1:
Программа представляет простейший «чат» (от англ. chat),
позволяющий обмениваться текстовыми сообщениями между двумя компьютерами.
В.1
клиент//------------------------------------------------------------------------------
#include <winsock>
#include <stdio.h>
#include <string>
#include <iostream>
//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
WSADATA wsa_data;
if (WSAStartup(0x101, &wsa_data) || wsa_data.wVersion != 0x101) return -1;
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == INVALID_SOCKET) return -1;
SOCKADDR_IN sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(2000);
sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
std::string message;
printf("message=");
getline(std::cin, message);
if
(
sendto
(
s,
message.c_str(), message.length() + 1,
0,
(SOCKADDR *)&sa, sizeof(sa)
) == SOCKET_ERROR
)
return -1;
closesocket(s);
WSACleanup();
system("pause");
return 0;
}
сервер
//------------------------------------------------------------------------------
#include <winsock>
#include <stdio.h>
//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
WSADATA wsa_data;
if (WSAStartup(0x101, &wsa_data) || wsa_data.wVersion != 0x101) return -1;
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == INVALID_SOCKET) return -1;
SOCKADDR_IN sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(2000);
sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (bind(s, (SOCKADDR *)&sa, sizeof(sa)) == SOCKET_ERROR) return -1;
SOCKADDR_IN nsa;
int sizeof_nsa = sizeof(nsa);
char buffer[1024];
int buffer_size = sizeof(buffer);
if
(
recvfrom(s, buffer, buffer_size, 0, (SOCKADDR *)&nsa, &sizeof_nsa) ==
SOCKET_ERROR
)
return -1;
printf("message=%s\n", buffer);
closesocket(s);
WSACleanup();
system("pause");
return 0;
}
В.2
клиент
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <algorithm>
#include <set>
using namespace std;
int main()
{
char message[1024];
char buf[sizeof(message)];
char nick[20];
std::string mes;
int sock;
struct sockaddr_in addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(10005);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(2);
}
std::cout<<"Nick? ";
std::cin>>nick;
for(;;)
{
std::cout<<nick<<": ";
std::cin>>message;
send(sock, message, sizeof(message), 0);
recv(sock, buf, sizeof(message), 0);
std::cout<<"Your friend: "<< buf <<"\n";
}
close(sock);
return 0;
}
сервер
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <algorithm>
#include <set>
#include <iostream>
using namespace std;
int main()
{
int listener;
struct sockaddr_in addr;
char buf[1024];
int bytes_read;
listener = socket(AF_INET, SOCK_STREAM, 0);
if(listener < 0)
{
perror("socket");
exit(1);
}
fcntl(listener, F_SETFL, O_NONBLOCK);
addr.sin_family = AF_INET;
addr.sin_port = htons(10005);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind");
exit(2);
}
listen(listener, 2);
set<int> clients;
clients.clear();
while(1)
{// Заполняем множество сокетов
fd_set readset;
FD_ZERO(&readset);
FD_SET(listener, &readset);
for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
FD_SET(*it, &readset);
timeval timeout;
timeout.tv_sec = 1000;
timeout.tv_usec = 0;
int mx = max(listener, *max_element(clients.begin(), clients.end()));
if(select(mx+1, &readset, NULL, NULL, &timeout) <= 0)
{
perror("select");
exit(3);
}
// Определяем тип события и выполняем соответствующие действия
if(FD_ISSET(listener, &readset))
{
// Поступил новый запрос на соединение, используем accept
int sock = accept(listener, NULL, NULL);
if(sock < 0)
{
perror("accept");
exit(3);
}
fcntl(sock, F_SETFL, O_NONBLOCK);
cout << "Socket accepted\n";
clients.insert(sock);
}
cout << "Before for\n";
for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
{
cout << "Before if\n";
if(FD_ISSET(*it, &readset))
{
// Поступили данные от клиента, читаем их
bytes_read = recv(*it, buf, 1024, 0);
cout << "read data buf = " << buf <<"\n";
if(bytes_read <= 0)
{
// Соединение разорвано, удаляем сокет из множества
close(*it);
clients.erase(*it);
continue;
}
for (set<int>::iterator its = clients.begin(); its != clients.end(); its++) if (it!=its) {
// Отправляем данные обратно клиенту
cout << "before send\n";
send(*its, buf, bytes_read, 0);
}
}
}
cout << "after for\n";
}
return 0;
}
Литература
К заданию №1
1. MSDN Library. Раздел Networking and Directory Services – Network Protocols – NetBIOS, раздел Networking and Directory Services – Network Management – Windows Networking (WNet).
2. Справочник по командам Windows. [Электрон, ресурс] / Режим досту-
па: http://winchanger.whatis.ru/file/prog.zip
3. Windows: Сети: Изучение TCP/IP. [Электрон, ресурс] / OS Zone. Режим
доступа: http://www.oszone.net/display.php?id=1409
4. К.Закер. Компьютерные сети. Модернизация и поиск неисправностей:
Пер. с англ. – СПб.: БХВ-Петербург, 2004. – 1008 с.: ил.
К заданию № 2
5. MSDN Library. Раздел Networking and Directory Services – Network Protocols – Windows Sockets.
6. Windows: Сети: Изучение TCP/IP: . [Электрон, ресурс] / OS Zone. Ре-
жим доступа: http://www.oszone.net/display.php?id=1409
7. К.Закер. Компьютерные сети. Модернизация и поиск неисправностей:
Пер. с англ. – СПб.: БХВ-Петербург, 2004. – 1008 с.: ил.