Здравствуйте,
вот ещё своял.. клиент. Тут сделано на скорую руку, так что могут быть недоработки, но на первый взгляд всё работает.
Клиент соединяется с сервером по введённому адресу и 5678 порту. Может посылать строку текста, принимать данные, определяет завершение сеодинения и сам может завершать соединение. Собственно, коегде по Ctrl+C, кое где по Ctrl+Z.. см. код..
Код, с моей точки зрения, полезен для изучения в режиме дебага, чтобы лучше понимать что где и как..
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#pragma comment (lib, "ws2_32.lib")
const int SERVER_PORT = 5678;
const int BUF_SIZE = 65535;
BOOL WINAPI HandlerRoutine(DWORD);
int main (void)
{
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
WSADATA wd;
WSAEVENT hEvents[2];
SOCKET sock;
WSANETWORKEVENTS wsEvents;
SOCKADDR_IN saddr;
DWORD dwDone = 0, dwBreak, dwTimeout;
int nRet;
char buf[BUF_SIZE];
bool fConnected, fWritePossible;
if(nRet = WSAStartup(MAKEWORD(2,0), &wd)){
cerr << "WSAStartup fail with code " << nRet << endl;
return -1;
}
hEvents[0] = static_cast<WSAEVENT>(CreateEvent(NULL, true, false, "StopProgrammEvent"));
if(!hEvents[0]){
cerr << "CreateEvent fail with code " << GetLastError () << endl;
return -2;
}
SetConsoleCtrlHandler(HandlerRoutine, true);
hEvents[1] = WSACreateEvent();
if (!hEvents[1]){
cerr << "WSACreateEvent fail with code " << WSAGetLastError() << endl;
return -3;
}
while(!dwDone){
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock == INVALID_SOCKET){
cerr << "socket fail with code " << WSAGetLastError() << endl;
return -4;
}
cin.clear();
do{
cout << "Enter IP address: ";
cin.getline(buf, BUF_SIZE);
if(cin.eof() || WaitForSingleObject(hEvents[0], 500) == 0){
cout << "StopProgrammEvent signaled.. Stopping.." << endl;
return 0;
}
}while(inet_addr(buf) == INADDR_NONE ||
inet_addr(buf) == INADDR_BROADCAST ||
inet_addr(buf) == INADDR_ANY);
ZeroMemory(&saddr, sizeof(SOCKADDR_IN));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(SERVER_PORT);
saddr.sin_addr.s_addr = inet_addr(buf);
if(WSAEventSelect(sock, hEvents[1], FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE)){
cerr << "WSAEventSelect fail with code " << WSAGetLastError () << endl;
return -6;
}
cout << "Try connection to " << buf << ":" << SERVER_PORT << "... ";
nRet = connect(sock, reinterpret_cast<SOCKADDR*>(&saddr), sizeof(SOCKADDR_IN));
if(nRet == SOCKET_ERROR){
nRet = WSAGetLastError();
if(nRet != WSAEWOULDBLOCK){
cerr << "connect fail with code " << WSAGetLastError() << endl;
return -7;
}
}
dwBreak = 0; fConnected = false; fWritePossible = true;
while(!dwBreak && !dwDone){
if(fConnected && fWritePossible){
cout << "Type string and press Enter: ";
cin.getline(buf, BUF_SIZE);
if(cin.eof()){
dwBreak = 1; break;
}
nRet = send(sock, buf, lstrlen(buf)+1, 0);
if(nRet == SOCKET_ERROR){
nRet = WSAGetLastError();
if(nRet != WSAEWOULDBLOCK){
cerr << "send fail with code " << nRet << endl;
break;
} else {
cout << "Process would block, try later.." << endl;
}
} else {
cout << "sending " << nRet << " bytes to server." << endl;
}
dwTimeout = 1000;
} else dwTimeout = WSA_INFINITE;
nRet = WSAWaitForMultipleEvents(2, hEvents, false, dwTimeout, false);
switch (nRet){
case WSA_WAIT_TIMEOUT: break;
case 0:
cout << "StopProgrammEvent signaled.. Stopping.." << endl;
dwDone = 1;
break;
case 1:
if(!WSAEnumNetworkEvents(sock, hEvents[1], &wsEvents)){
if(wsEvents.lNetworkEvents & FD_CONNECT){
if(wsEvents.iErrorCode[FD_CONNECT_BIT]){
cerr << "FD_CONNECT fail witch code " <<
wsEvents.iErrorCode[FD_CONNECT_BIT] << endl;
dwBreak = 1;
} else {
cout << "connected." << endl;
fConnected = true;
}
}
if(wsEvents.lNetworkEvents & FD_WRITE){
if(wsEvents.iErrorCode[FD_WRITE_BIT]){
cerr << "FD_WRITE fail. Stopping.." << endl;
dwDone = 1;
break;
} else {
if(!fWritePossible){
nRet = send(sock, buf, lstrlen(buf), 0);
if(nRet == SOCKET_ERROR){
nRet = WSAGetLastError();
if(nRet != WSAEWOULDBLOCK){
cerr << "send fail with code " << nRet << endl;
dwBreak = 1;
break;
} else {
cout << "Process would block, try later.." << endl;
}
} else {
cout << "sending " << nRet << " bytes to server." << endl;
}
}
fWritePossible = true;
}
}
if(wsEvents.lNetworkEvents & FD_READ){
if(wsEvents.iErrorCode[FD_READ_BIT]){
cerr << "FD_READ fail. Stopping.." << endl;
dwDone = 1;
break;
} else {
nRet = recv(sock, buf, BUF_SIZE, 0);
if(nRet > 0) cout << "Received " << nRet << "bytes" << endl;
}
}
if(wsEvents.lNetworkEvents & FD_CLOSE){
if(wsEvents.iErrorCode[FD_CLOSE_BIT]){
cerr << "FD_CLOSE fail with code " << wsEvents.iErrorCode[FD_CLOSE_BIT] << endl;
if(wsEvents.iErrorCode[FD_CLOSE_BIT] == WSAENETDOWN){
cerr << "Stopping.." << endl;
dwDone = 1;
} else dwBreak = 1;
} else {
cout << "Client disconnected." << endl;
dwBreak = 1;
}
break;
}
} else {
cerr << "WSAEnumNetworkEvent fail with code " << WSAGetLastError() << endl;
WSAResetEvent(hEvents[2]);
}
break;
default:
cerr << "WSAWaitForMultipleEvents return " << nRet <<" with error code "
<< WSAGetLastError() << endl;
}
}
WSAEventSelect(sock, hEvents[1], 0);
shutdown(sock, SD_BOTH);
closesocket(sock);
cerr << "connection closed.." << endl;
}
WSACloseEvent(hEvents[1]);
CloseHandle(hEvents[0]);
WSACleanup();
return 0;
}
BOOL WINAPI HandlerRoutine(DWORD)
{
HANDLE hEvent;
hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "StopProgrammEvent");
if(hEvent){
SetEvent(hEvent);
CloseHandle(hEvent);
return true;
}
return false;
}