Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[WinSock]Klient?

Ostatnio zmodyfikowano 2011-10-18 18:00
Autor Wiadomość
FucktheSystem
Temat założony przez niniejszego użytkownika
[WinSock]Klient?
» 2011-10-18 17:51:52
Witam przeczytałem kurs (nie z tej strony) o WinSock. Przerobiłem nieznacznie przykładowy kod serwera i napisałem do niego klient. Niestety klient nie działa tak dobrze jak telnet. W czym rzecz?


Server
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string>

#define MAX_CLIENTS 20

using namespace std;

// kontekst klienta
struct ClientContext
{
HANDLE thread;
SOCKET sock;
int id;
};

// socket serwera
SOCKET sock;
// klienci
ClientContext clients[MAX_CLIENTS];

void ShutdownServer()
{
// zamykamy niezamknięte socket'y klientów
for (int i = 0; i < MAX_CLIENTS; i++)
if (clients[i].sock != INVALID_SOCKET)
{
closesocket (clients[i].sock);
clients[i].sock = INVALID_SOCKET;
}

closesocket (sock);
sock = INVALID_SOCKET;
}

DWORD WINAPI processClient (LPVOID ctx)
{
ClientContext *context = (ClientContext*)ctx;
string message = "Welcome to BnB v0.1\n\r";
string inputString;
char inputBuffer[513];
int ret;
char *ptr;

cout << "Klient o ID " << context->id << " podlaczony!\n";

// wysyłamy komunikat
send(context->sock, message.c_str(), message.size()+1, 0);

memset(inputBuffer, 0, 513);
inputString = "";

while (1)
{
ret = recv(context->sock, inputBuffer, 512, 0);
cout << ret << "\n";
cout << inputBuffer << "\n";

if (ret == 0)
{
// połączenie zamknięte po stronie klienta
cout << "Klient zamknął połączenie z serwerem.\n";
closesocket (context->sock);
context->sock = INVALID_SOCKET;
break;
}
else if (ret == SOCKET_ERROR)
{
cout << "Klient zamknął połączenie z serwerem.\n";
closesocket (context->sock);
context->sock = INVALID_SOCKET;
break;
}

// sprawdzamy czy odebralismy znak konca linii
if((ptr = strchr(inputBuffer, '\n')) != NULL)
{
// jezeli tak to wstawiamy terminatora
ptr --;
*ptr = 0;

// dodajemy do wejsciowego stringa
inputString += inputBuffer;

// sprawdzamy jaka komenda zostala wyslana
if (inputString == "exit")
{
cout << "Klient prosi o rozlaczenie\n";
closesocket (context->sock);
context->sock = INVALID_SOCKET;
break;
}
else if (inputString == "kill server")
{
// jezeli klient chce wylaczyc serwer to bezposrednio zamykamy
// scketa z ktorego korzysta serwer
cout << "Klient prosi o zamkniecie serwera\n";
ShutdownServer();
break;
}
else
{
// jezeli klient nie wyslal zadnej z powyzszych komend odpisujemy mu tym samym
message = string("Napisales: ") + inputString + "\n\r";
send(context->sock, message.c_str(), message.size()+1, 0);
}

// czyscimy bufory
memset(inputBuffer, 0, 512);
inputString = "";
}
else
{
// jezeli nie ma konca linii to dopisujemy nowe dane do bufora wejsciowego
// a nastepnie "doklejamy" do bufora komendy
inputBuffer[ret] = 0;
inputString += inputBuffer;
}
}

context->thread = NULL;
return 0;
}

int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKADDR_IN saddr;
SOCKET client;
int processConnections = 5;
int newId;

// zerujemy konteksty klientów
for (int i = 0; i < MAX_CLIENTS; i ++)
{
clients[i].thread = NULL;
clients[i].sock   = INVALID_SOCKET;
clients[i].id     = -1;
}

// uruchamiamy serwer, to juz umiemy
WSAStartup( MAKEWORD(2,2), &wsaData );

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
memset( (void*)&saddr, 0, sizeof(saddr) );
saddr.sin_family = AF_INET;
saddr.sin_port = htons(10000);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);

if ( bind(sock, (sockaddr*)&saddr, sizeof(saddr)) == SOCKET_ERROR )
{
cout << "Wystąpił błąd podczas bindowania adresu!\n";
return -1;
}

if (listen(sock, MAX_CLIENTS) == SOCKET_ERROR)
{
cout << "Ustawienie gniazda w tryb nasłuchiwania nie powiodło się\n";
closesocket (sock);
return -2;
}

while (1)
{
// akceptujemy nowego klienta
client = accept(sock, NULL, NULL);

if (client == INVALID_SOCKET)
{
// jeżeli dostajemy WSAENOTSOCKET to znaczy, ze ktorys z klientow zamknal
// naszego nasluchujacego socketa
if (WSAGetLastError() == WSAECONNRESET)
{
cout << "WSAECONNRESET\n";
}
else
break;
}
else
{
// szukamy wolnego slota
newId = -1;
for (int i = 0; i < MAX_CLIENTS; i ++)
if (clients[i].sock == INVALID_SOCKET)
{
newId = i;
break;
}

if (newId == -1)
{
cout << "Serwer nie obsluguje wiekszej ilosci klientow jednoczesnie niz " << MAX_CLIENTS << endl;
}
else
{
// dodajemy nowego klienta i startujemy wątek
clients[newId].sock   = client;
clients[newId].id     = newId;
clients[newId].thread = CreateThread (NULL, 0, processClient, (LPVOID)&clients[newId], 0, NULL);

// utworzenie wątku nie powiodło się
if (clients[newId].thread == NULL)
{
clients[newId].sock = INVALID_SOCKET;
clients[newId].id   = -1;
cout << "Utworzenie watku dla klienta nie powiodlo sie." << endl;
}
}
}
}

// serwer zakonczyl dzialanie, tworzymy tablice uchwytów wątków
HANDLE threads[MAX_CLIENTS];
int threadsCount = 0;

// uzupełniamy tablicę
for (int i = 0; i < MAX_CLIENTS; i++)
if (clients[i].thread != NULL)
{
threads[threadsCount] = clients[i].thread;
threadsCount ++;
}

// czekamy 5 sekund i w ostatecznosci zabijamy watki
if (WaitForMultipleObjects(threadsCount, threads, true, 5000) == WAIT_TIMEOUT)
for (int i = 0; i < MAX_CLIENTS; i ++)
TerminateThread (threads[i], 2);

WSACleanup();
system("pause");
return 0;
}

Client
#include <winsock2.h>
#include <windows.h>
#include <conio.h>
#include <iostream>
#include <string>



using namespace std;


int main()
{
    WSADATA       wsd;
    SOCKET        Client;
    sockaddr_in server;
    hostent    *host = NULL;
char InputBuffer[513];                    
int iPort     = 10000;
string komenda;

cout << "Podaj IP: ";
cin >> InputBuffer;


    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
cout << "Nie mozna stworzyc WinSock'a." << endl;
        return 1;
    }

    Client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (Client == INVALID_SOCKET)
    {
cout << "Nie mozna utworzyc gniazda (" << WSAGetLastError() << ")." << endl;
        return 1;
    }

    server.sin_family = AF_INET;
    server.sin_port = htons(10000);
    server.sin_addr.s_addr = inet_addr(InputBuffer);

    if (server.sin_addr.s_addr == INADDR_NONE)
    {
        host = gethostbyname(InputBuffer);
        if (host == NULL)
        {
cout << "Nie mozna przeksztalcic na ip: " << InputBuffer << endl;
            return 1;
        }
        CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length);
    }

    if (connect(Client, (sockaddr *)&server,
        sizeof(server)) == SOCKET_ERROR)
    {
cout << "Nie mozna sie polaczyc (" << WSAGetLastError() << ")." << endl;
        return 1;
    }

cout << "Polaczono." << endl;


while(1)
{
recv(Client,InputBuffer,512,0);
std::cout << InputBuffer << endl;
std::cout << "What is ur wish?\n";
std::cin >> komenda;
std::cout << "";
int ret = send(Client, komenda.c_str(), komenda.size()+1, 0);
std::cout << ret << "\n";
std::cout << komenda << "\n";
}
}

P-42283
Drraven
» 2011-10-18 17:57:53
Polecam metodę prób i błedów.
Nikt za ciebie nie będzie odwalał roboty.
P-42285
FucktheSystem
Temat założony przez niniejszego użytkownika
...
» 2011-10-18 18:00:07
Właśnie zauważyłem, że ten serwer czeka na chary aż do zakończenia linii. ('\n')

Dalej kombinuje co z tym zrobić. :/

EDIT:

Wszystko działa jak należy. :D
Nie potrzebnie temat zakładałem.
P-42287
« 1 »
  Strona 1 z 1