Home - qdidactic.com
Didactica si proiecte didacticeBani si dezvoltarea cariereiStiinta  si proiecte tehniceIstorie si biografiiSanatate si medicinaDezvoltare personala
referate stiintaSa fii al doilea inseamna sa fii primul care pierde - Ayrton Senna





Aeronautica Comunicatii Drept Informatica Nutritie Sociologie
Tehnica mecanica

Retele calculatoare


Qdidactic » stiinta & tehnica » informatica » retele calculatoare
Crearea unui soclu care asculta Winsock - pragma comment



Crearea unui soclu care asculta Winsock - pragma comment



Pentru a putea folosi Winsock inainte de a scrie orice cod trebuie sa includem wsock32.dll cu instructiunea :


#pragma comment(lib, “wsock32.lib”)


In mod normal un soclu care asculta asteptand o cerere de conexiune este numit server .

Odata ce conexiunea s-a creat el creeaza un nou fir care va trata conexiunea creata.


Pentru a crea un soclu sa vedem intai de ce structuri avem nevoie.


WSDATA:


Orice cod de program care se compileaza folosind winsock acceseaza ws2_32.dll , aceasta structura fiind folosita in acest process. .Programul trebuie sa cheme WSAstartup ca sa initializeze DLL-ul ptr. folosirea lui ulterioara.


SOCKADDR_IN:



Aceasta structura ne arata cum va fi folosit soclul creat si contine un camp ptr. adresa IP si un camp ptr. adresa de port.


SOCKET:


mySock = socket(family, type, protocol);






Family

Type

Protocol

TCP

PF_INET

SOCK_STREAM

IPPROTO_TCP

UDP

SOCK_DGRAM

IPPROTO_UDP


Este un obiect care va stoca un descriptor al soclului.


Functiile necesare ptr. crearea unui soclu care asculta


WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData )


Aceasta este prima functie care trebuie apelata de orice aplicatie sau dll.Ea permite aplicatiei sau dll-ului sa specifice versiunea necesara de Windows Sockets API si verifica ce versiune de Windows Sockets este instalata.Numai dupa invocarea cu success a acestei functii aplicatia sau dll-ul poate invoca alte functii Windows Sockets API.


socket(int af, int type, int protocol)


Aceasta metoda va crea un soclu.


bind(SOCKET s, const struct sockaddr FAR * name, int namelen)

Aceasta functie asociaza o adresa locala cu un soclu.Acesata rutina este folosita ptr.o datagrama sau un socket stream neconectat,deci inainte de a se stabili conexiunea sau de blocarea in starea listen.Cand creem un soclu cu socket , el va exista intr-un spatiu de nume definit de campul(address family),
Dar nu va avea un nume alocat pana cand bind va stabili asocierea (adresa loala/numar port) dand un nume soclului creat cu socket.
In spatial de adrese de familie de tip Internet,un nume are mai multe componente.
Ptr. tipurile SOCK_DGRAM si SOCKET_STREAM numele are trei parti : adresa loala,numar protocol(UDP sau TCP) si un nr. de port care identifica aplicatia
Care solicita accesul pe soclul creat.
Daca ptr. o aplicatie nu conteaza adresa locala se poate specifica in campul de adresa valoarea INNADDR_ANY,ca nr. port 0,sau amandoua.
Daca se foloseste INNADDR_ANY,va fi folosita orice interfata de retea potrivita aplicatiei.
Daca specificam ca nr. port 0 Windows Sockets va aloca un nr. de port intre 1055-5000.
Aplicatia poate insa sa folosesca functia gethostbyname dup ace s-a folosit bind ptr. a gas ice adresa a fost alocata ,dar gethostbyname nu va returna nici o adresa pana cand soclul nu va fi conectat.
Daca nu exista erori bind va returna 0.
Altfel retuneaza SOCKET_ERROR cu un cod de eroare specific ei care poate fi citit folosind functia: WSAGetLastError .


listen(SOCKET s, int backlog )

Seteaza un soclu sa asculte cereri de conectare .Ptr. a accepta conexiuni un soclu trebuie intai creat co socket si un buffer backlog va fi specificat cu listen ,unde vor fi memorate cererile de conectare sosite, care vor fi acceptate cu accept .Listen se aplica doar conexiunilor de tipul SOCKET_STREAM.
Soclul s este pus in stare pasiva asteptand cereri de conectare pe acre le pune in coada de asteptare pana cand procesul poate sa le serveasca.(accepte).
Functia este tipica serverelor care pot primi cereri simultane de conectare.
Daca soseste o cerere de conectare cand bufferul(coda) e plin clientul care a solicitat conectarea va primi un mesaj de eroare WSACONNREFUSED.
Listen accepta conexiuni pana cand bufferul se umple.


accept(SOCKET s, struct sockaddr FAR * addr, int FAR * addrlen)

Aceasta rutina extrage prima cerere de conectare din coada soclului s ,creaza un nou soclu cu aceleasi proprietati ca s si returneaza un descriptor al noului soclu creat.
Daca in coada nu mai exista cereri de conectare si daca soclul nu este marcat ca non-blocking accept blocheaza clientul pana la stabilirea conexiunii.
Daca soclul este marcat ca non-blocking sin u existe cereri in coada accept returneaza eroare.Soclul nou creat nu mai poate accepta noi cereri de conectare dar soclul initial ramane in starea listen.
Argumentul addr este un parametru ce va fi incarcat cu adresa conexiunii create de la nivelul data link communication layer.
Formatul parametrului addr este dictat de familia de adrese folosita la crearea soclului.
Addrlen va contine initial spatial indicat de addr iar dupa invocarea accept va
Contine lungimea actuala in octeti a adresei returnate.
Daca addr sau addrlen sunt NULL atunci accept nu returneaza nimic despre adresa soclului acceptat.


closesocket(SOCKET s)

inchide un soclu.

WSACleanup()

Termina folosirea Windows Sockets DLL.

Exemplu 1.

#include <stdio.h>
#include <winsock.h>
#include <windows.h>

#define SERVER_SOCKET_ERROR 1
#define SOCKET_OK 0

#pragma comment(lib, 'wsock32.lib')

void socketError(char*);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShow)


//fill in sockaddr_in struct

SOCKADDR_IN sin;
sin.sin_family = PF_INET;
sin.sin_port = htons( );
sin.sin_addr.s_addr = INADDR_ANY;

//bind the socket
rVal = bind(s, (LPSOCKADDR)&sin, sizeof(sin));
if(rVal == SOCKET_ERROR)


//get socket to listen
rVal = listen(s, );
if(rVal == SOCKET_ERROR)


//wait for a client
SOCKET client;

client = accept(s, NULL, NULL);

if(client == INVALID_SOCKET)


//close process
closesocket(client);
closesocket(s);

WSACleanup();

return SOCKET_OK;


void socketError(char* str)


Conectarea unui client la server

In plus fata de struturile deja folosite vom folosi structura

HOSTENT:

Structura este folosita ptr. a indica soclului la care calculator sa se conectee sip e ce port.Structura folosita este LPHOSTENT ca poiter la structura HOSTENT.

Functii cheie ptr. aplicatia client

gethostbyname(const char* FAR name)

Returneaza un pointer la o structura HOSTENT.Continutul structurii corespunde cu numele gazdei.Poiterul va indica spre structura folosita de implementarea Windows Sckets.
Gethostby name nu trebuie sa resolve adresa IP care a primit-o.
Ptr. a converti sirul de caractere in adresa in format IP se va folosi inet_addr si apoi gethostbyaddr ptr. a obtine structura HOSTENT.

Exemplul 2.

#include <windows.h>
#include <winsock.h>

#pragma comment(lib, 'wsock32.lib')

#define CS_ERROR 1
#define CS_OK 0

void sError(char*);

int WINAPI WinMain(HINSTANCE hHinst, HINSTANCE hPrevHinst, LPSTR lpCmdLine,
int nShow)


//create the socket
SOCKET theSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

if(theSocket == SOCKET_ERROR)


//Fill in the sockaddr_in struct
SOCKADDR_IN serverInfo;

serverInfo.sin_family = PF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);

serverInfo.sin_port = htons( );

rVal=connect(theSocket,(LPSOCKADDR)&serverInfo, sizeof(serverInfo));
if(rVal==SOCKET_ERROR)


closesocket(theSocket);
WSACleanup();
MessageBox(NULL, 'Connection was made', 'SOCKET', MB_OK);
return CS_OK;


void sError(char *str)


Trimiterea si receptionarea pachetelor


send(SOCKET s, const char FAR * buf, int len, int flags)

send se foloseste ptr. a trimite date la in soclu creat.
Ptr. datagrame trebuie san u depasim lungimea maxima a unui pachet IP care este data in iMaxUdpDg din structura WSAData.
Daca pachetul este mai mare decat acest parametru se returneaza eroarea WSAEMSGSIZE sin u se transmite nimic.


recv(SOCKET s, const char FAR * buf, int len, int flags)

Ptr. SOCKET_STREM toata informatia disponibila pana la dimensiunea bufferului este receptionata.

Exemplu 3.

client = accept(s, NULL, NULL);

cout << 'newclient found' << endl;

if(client == INVALID_SOCKET)


char buf[ ];
rVal = recv(client, buf, , );

if(rVal == SOCKET_ERROR)

else if(val == WSAESHUTDOWN )

socketError('Failed recv()');
return SERVER_SOCKET_ERROR;
}

cout << buf << endl;


Programul de mai sus functioneaza bine daca stim exct lungimea pachetului de date ce se receptioneaza.

Implementarea functiei send se face astfel :

rVal=connect(theSocket,(LPSOCKADDR)&serverInfo, sizeof(serverInfo));

if(rVal==SOCKET_ERROR)


char *buf = 'data';

rVal = send(theSocket, buf, strlen(buf), );

if(rVal == SOCKET_ERROR)



Daca nu cunoastem lungimea pachetului de date ce se va receptiona ,
Vom proceda astfel :

Vom crea o noua functie care va primi un pointer catre soclul client,si va citi apoi cate un character odata plasand caracterele intr-un vector pana cand intalneste caracterul “/n” care specifica sfarsitul mesajului.
Functia va fi apelata dup ace se executa accept.

char * readline(SOCKET *client)

socketError('Failed recv()');
WSACleanup();
}

if(buffer == 'n')


cout << data << endl;
return data;
}
else

}








Contact |- ia legatura cu noi -| contact
Adauga document |- pune-ti documente online -| adauga-document
Termeni & conditii de utilizare |- politica de cookies si de confidentialitate -| termeni
Copyright © |- 2024 - Toate drepturile rezervate -| copyright