370 likes | 570 Views
计算机网络. ——Programming With Sockets Week 5 2000/10/09. 教学安排. Windows 套接字 API 客户端软件设计 客户端实现例程. Windows 套接字规范. Windows 套接字规范以 U.C. Berkeley 大学 BSD UNIX 中流行的套接字接口为范例定义了一套微软 Windows 下的网络编程接口。除了包含 Berkeley Socket 风格的库函数外,还有一组针对 Windows 的扩展库函数,以使程序员能充分利用 Windows 消息驱动机制进行编程。
E N D
计算机网络 ——Programming With Sockets Week 5 2000/10/09
教学安排 • Windows套接字API • 客户端软件设计 • 客户端实现例程
Windows套接字规范 • Windows套接字规范以U.C. Berkeley大学BSD UNIX中流行的套接字接口为范例定义了一套微软Windows下的网络编程接口。除了包含Berkeley Socket风格的库函数外,还有一组针对Windows的扩展库函数,以使程序员能充分利用Windows消息驱动机制进行编程。 • Windows套接字规范定义并记录了如何使用API与Internet协议族连接。所有的Windows套接字实现都支持流套接字和数据报套接字。
WinSock API头文件 • # include <winsock.h> • # include <winsock2.h>
WSAStartup( ) #include <winsock.h> int PASCAL FAR WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData ); wVersionRequested:最高版本号 lpWSAData:指向WSADATA数据结构的指针 必须是应用程序或DLL调用的第一个Windows套接字函数。它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节。
WSACleanup( ) 中止Windows Sockets DLL的使用. #include <winsock.h> int PASCAL FAR WSACleanup ( void ); 应用程序完成Windows Sockets的使用后, 必须调用WSACleanup()将其从Windows Sockets的实现中注销,并且释放为应用程序分配的任何资源。任何打开的并已建立连接的SOCK_STREAM类型套接字在调用WSACleanup()时会重置。
Shutdown( ) 禁止在一个套接字上进行数据的接收与发送。 #include <winsock.h> int PASCAL FAR shutdown( SOCKET s, int how); s:用于标识一个套接字的描述字。 how:标志,用于描述禁止哪些操作。 用于任何类型的套接字禁止接收、禁止发送或禁止收发。但并不关闭套接字,且套接字所占用的资源将被一直保持到closesocket()调用。
Select( ) 确定一个或多个套接口的状态,如需要则等待。 #include <winsock.h> int PASCAL FAR select( int nfds, fd_set FAR* readfds, fd_set FAR* writefds, fd_set FAR* exceptfds, const struct timeval FAR* timeout); nfds:本参数忽略,仅起到兼容作用。 readfds:(可选)指针,指向一组等待可读性检查的套接口。 writefds:(可选)指针,指向一组等待可写性检查的套接口。 exceptfds:(可选)指针,指向一组等待错误检查的套接口。 timeout:select()最多等待时间,对阻塞操作则为NULL。
TCP客户程序算法 1. Find the IP address and protocol port number of the server with which communication is desired. 2. Allocate a socket. 3. Specify that the connection needs an arbitrary, unused protocol port on the local machine, and allow TCP to choose one. 4. Connect the socket to the server. 5. Communicate with the server using the application-level protocol (this usually involves sending requests and awaiting replies.) 6. Close the connection.
sockaddr_in结构 struct sockaddr_in { /* struct to hold an address */ u_short sin_family; /* type of address (AF_INET) */ u_short sin_port; /* protocol port number */ struct in_addr sin_addr; /* IP address ( declared to be */ /* u_long on some systems ) */ char sin_zero[8]; /* unused (set to zero ) */ };
确定服务器地址 • IP address in dotted decimal notation, e.g. 210.32.141.14 inet_addr ( ) struct sockaddr_in sin; char *examplename = “210.32.141.14”; sin.sin_addr.s_addr = inet_addr ( examplename ); • domain name, e.g. zhoujf.isee.zju.edu.cn gethostbyname ( )
Hostent结构 struct hostent { char FAR* h_name; /* official host name */ char FAR* FAR* h_aliases; /* other aliases */ short h_addrtype; /* address type */ short h_length; /* address length */ char FAR* FAR* h_addr_list; /* list of addresses */ }; # define h_addr h_addr_list[0]
由服务器域名确定地址 struct hostent *hptr; char *examplename = “zhoujf.isee.zju.edu.cn”; if ( hptr = gethostbyname( examplename ) ) { /* IP address is now in hptr->h_addr */ } else { /* error in name - handle it */ }
servent 结构 struct servent { char FAR* s_name; /* official service name */ char FAR* FAR* s_aliases; /* other aliases */ short s_port; /* port for this service */ char FAR* s_proto; /* protocol to use */ };
由服务名确定端口号 struct servent *sptr; if ( sptr = getservbyname( “smtp”, “tcp” ) ) { /* port number is now in sptr->s_port */ } else { /* error occurred - handle it */ }
Protoent结构 struct protoent { char FAR* p_name; /* official protocol name */ char FAR* FAR* p_aliases; /* other aliases */ short p_proto; /* official protocol number */ };
由协议名确定协议号 struct protoent *pptr; if ( pptr = getprotobyname( “udp” ) ) { /* official protocol number is now in pptr->p_proto */ } else { /* error occurred - handle it */ }
创建套接字 # include <winsock.h> SOCKET s; s = socket (PF_INET, SOCK_STREAM, 0) if ( s == INVALID_SOCKET ) { /* error occurred - handle it */ }
与服务器建立连接 # include <winsock.h> struct sockaddr_in sin; SOCKET s; if ( connect (s, (struct sockaddr * )&sin, sizeof(sin) ) == SOCKET_ERROR) { /* error occurred - handle it */ }
与服务器通信 #define BLEN 120 /* buffer length to use */ char *req = “request of some sort”; char buf[BLEN]; /* buffer for answer */ char *bptr; /* pointer to buffer */ int n; /* number of bytes read*/ int buflen; /* space left in buffer */ bptr = buf; buflen = BLEN; /* send request */ send (s, req, strlen(req), 0); /* read response (may come in many pieces) */ n = recv (s, bptr, buflen, 0); while ( n != SOCKET_ERROR && n != 0) { bptr += n; buflen -= n; n = recv (s, bptr, buflen, 0); }
关闭TCP连接 • Partial close operation shutdown (s, direction) • Close a socket closesocket (s)
UDP客户程序算法 1. Find the IP address and protocol port number of the server with which communication is desired. 2. Allocate a socket. 3. Specify that the communication needs an arbitrary, unused protocol port on the local machine, and allow UDP to choose one. 4. Specify the server to which messages must be sent. 5. Communicate with the server using the application-level protocol (this usually involves sending requests and awaiting replies). 6. Close the socket.
Client端实现示例 • A TCP client for the DAYTIME service • A UDP client for the TIME service • A TCP client for the ECHO service • A UDP client for the ECHO service
ConnectTCP例程 # include <winsock.h> SOCKET connectsock(const char *, const char *, const char *) /* connectTCP - connect to a specified TCP service on a specified host */ SOCKET connectTCP(const char *host, const char *service) { return connectsock( host, service, “tcp”); } conTCP.cpp
ConnectUDP例程 # include <winsock.h> SOCKET connectsock(const char *, const char *, const char *) /* connectTCP - connect to a specified UDP service on a specified host */ SOCKET connectTCP(const char *host, const char *service) { return connectsock( host, service, “udp”); } conUDP.cpp
ConnectSock过程 consock.cpp
Errexit过程 errexit.cpp
DAYTIME服务 • Protocol Port 13 • RFC 867 • A TCP client for the DAYTIME service
DAYTIME服务TCP客户端 TCPdtc.cpp
TIME服务 • Protocol Port 37 • RFC 868 • A UDP client for the TIME service
TIME服务UDP客户端 UDPtime.cpp
ECHO服务 • Protocol Port 13 • RFC 862 • A TCP client for the ECHO service • A TCP client for the ECHO service
ECHO服务TCP客户端 TCPecho.cpp
ECHO服务UDP客户端 UDPecho.cpp