进程间通讯总结 (6)

来源:互联网 发布:mac上电话轰炸 编辑:程序博客网 时间:2024/05/22 06:50

Using Windows Sockets for IPC

Windows Socketsis a protocol-independent interface. It takes advantage of the communication capabilities of the underlying protocols.

Socket是什么呢?
       Socket是应用层与TCP/IP协议族通信的中间软件抽象层,是对TCP/IP协议的封装。socket本身不算是协议。而是一组调用接口(API),通过Socket,我们才能使用TCP/IP协议。实际上,SocketTCP/IP协议没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以说,socket的出现只是使得程序员更方便地使用TCP/IP协议而已,是对TCP/IP协议的抽象。对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议

Windows Sockets2 (Winsock) enables programmers to create advanced Internet, intranet, and other network-capable applications to transmit application data across the wire, independent of the network protocol being used. In Windows Sockets 2, a socket handle can optionally be used as a file handle with the standard file I/O functions.

There are two distinct types of socket network applications: Server and Client.What follows is the general model for creating a streaming TCP/IP Server and Client.

Server

  1. Initialize Winsock.
  2. Create a socket.
  3. Bind the socket.
  4. Listen on the socket for a client.
  5. Accept a connection from a client.
  6. Receive and send data.
  7. Disconnect.

Client

  1. Initialize Winsock.
  2. Create a socket.
  3. Connect to the server.
  4. Send and receive data.
  5. Disconnect.
Code sample:
Server:
#undef UNICODE#define WIN32_LEAN_AND_MEAN#include <windows.h>#include <winsock2.h>#include <ws2tcpip.h>#include <stdlib.h>#include <stdio.h>#pragma comment(lib, "Ws2_32.lib")#define DEFAULT_BUFLEN 512#define DEFAULT_PORT "27015"int main() {WSADATA wsaData;int iResult;SOCKET ListenSocket = INVALID_SOCKET;SOCKET ClientSocket = INVALID_SOCKET;struct addrinfo *result = NULL, hints;int iSendResult;char recvbuf[DEFAULT_BUFLEN];int recvbuflen = DEFAULT_BUFLEN;// 1) **** Initialize Winsock// The WSAStartup function is called to initiate use of WS2_32.dll.iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}ZeroMemory(&hints, sizeof (hints));hints.ai_family = AF_INET;hints.ai_socktype = SOCK_STREAM;hints.ai_protocol = IPPROTO_TCP;hints.ai_flags = AI_PASSIVE;// Resolve the local address and port to be used by the serveriResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);if (iResult != 0) {printf("getaddrinfo failed: %d\n", iResult);WSACleanup();return 1;}// 2) **** Create a socket.// Create a SOCKET for the server to listen for client connectionsListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);if (ListenSocket == INVALID_SOCKET) {printf("Error at socket(): %ld\n", WSAGetLastError());freeaddrinfo(result);WSACleanup();return 1;}// 3) **** Bind the socket.// Setup the TCP listening socket// Call the bind function, passing the created socket and sockaddr structure returned from the getaddrinfo function as parameters. iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);if (iResult == SOCKET_ERROR) {printf("bind failed with error: %d\n", WSAGetLastError());freeaddrinfo(result);closesocket(ListenSocket);WSACleanup();return 1;}// Once the bind function is called, the address information returned by the getaddrinfo function is no longer needed. freeaddrinfo(result);// 4) **** Listen on the socket for a client.// listen on that IP address and port for incoming connection requests// the backlog parameter was set to SOMAXCONN. // This value is a special constant that instructs the Winsock provider for this socket to allow a maximum reasonable number of pending connections in the queue.if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {printf("Listen failed with error: %ld\n", WSAGetLastError());closesocket(ListenSocket);WSACleanup();return 1;}// 5) **** Accept a connection from a clientClientSocket = accept(ListenSocket, NULL, NULL);if (ClientSocket == INVALID_SOCKET) {printf("accept failed: %d\n", WSAGetLastError());closesocket(ListenSocket);WSACleanup();return 1;}// No longer need server socketclosesocket(ListenSocket);// 6) **** Receive and send data.// Receive until the peer shuts down the connectiondo {iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);if (iResult > 0) {printf("Bytes received: %d\n", iResult);// Echo the buffer back to the senderiSendResult = send(ClientSocket, recvbuf, iResult, 0);if (iSendResult == SOCKET_ERROR) {printf("send failed with error: %d\n", WSAGetLastError());closesocket(ClientSocket);WSACleanup();return 1;}printf("Bytes sent: %d\n", iSendResult);}else if (iResult == 0)printf("Connection closing...\n");else  {printf("recv failed with error: %d\n", WSAGetLastError());closesocket(ClientSocket);WSACleanup();return 1;}} while (iResult > 0);// 7) **** Disconnect// shutdown the connection since we're doneiResult = shutdown(ClientSocket, SD_SEND);if (iResult == SOCKET_ERROR) {printf("shutdown failed with error: %d\n", WSAGetLastError());closesocket(ClientSocket);WSACleanup();return 1;}// cleanupclosesocket(ClientSocket);WSACleanup();return 0;}

Client:
#define WIN32_LEAN_AND_MEAN#include <windows.h>#include <winsock2.h>#include <ws2tcpip.h>#include <stdlib.h>#include <stdio.h>// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib#pragma comment (lib, "Ws2_32.lib")#pragma comment (lib, "Mswsock.lib")#pragma comment (lib, "AdvApi32.lib")#define DEFAULT_BUFLEN 512#define DEFAULT_PORT "27015"int main(int argc, char **argv){WSADATA wsaData;SOCKET ConnectSocket = INVALID_SOCKET;struct addrinfo *result = NULL,*ptr = NULL,hints;char *sendbuf = "this is a test";char recvbuf[DEFAULT_BUFLEN];int recvbuflen = DEFAULT_BUFLEN;int iResult;// Validate the parametersif (argc != 2) {printf("usage: %s server-name\n", argv[0]);return 1;}// 1) **** Initialize WinsockiResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed with error: %d\n", iResult);return 1;}ZeroMemory(&hints, sizeof(hints));hints.ai_family = AF_UNSPEC;hints.ai_socktype = SOCK_STREAM;hints.ai_protocol = IPPROTO_TCP;// Resolve the server address and portiResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);if (iResult != 0) {printf("getaddrinfo failed with error: %d\n", iResult);WSACleanup();return 1;}// Attempt to connect to an address until one succeedsfor (ptr = result; ptr != NULL; ptr = ptr->ai_next) {// 2) **** Create a SOCKET for connecting to serverConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);if (ConnectSocket == INVALID_SOCKET) {printf("socket failed with error: %ld\n", WSAGetLastError());WSACleanup();return 1;}// 3) **** Connect to server.iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);if (iResult == SOCKET_ERROR) {closesocket(ConnectSocket);ConnectSocket = INVALID_SOCKET;continue;}break;}freeaddrinfo(result);if (ConnectSocket == INVALID_SOCKET) {printf("Unable to connect to server!\n");WSACleanup();return 1;}// 4) **** Send an initial bufferiResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);if (iResult == SOCKET_ERROR) {printf("send failed with error: %d\n", WSAGetLastError());closesocket(ConnectSocket);WSACleanup();return 1;}printf("Bytes Sent: %ld\n", iResult);// shutdown the connection since no more data will be sent// When the client is done sending data to the server, the shutdown function can be called specifying SD_SEND to shutdown the sending side of the socket.// the client can still use the ConnectSocket for receiving dataiResult = shutdown(ConnectSocket, SD_SEND);if (iResult == SOCKET_ERROR) {printf("shutdown failed with error: %d\n", WSAGetLastError());closesocket(ConnectSocket);WSACleanup();return 1;}// 5) **** Receive until the peer closes the connectiondo {iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);if (iResult > 0)printf("Bytes received: %d\n", iResult);else if (iResult == 0)printf("Connection closed\n");elseprintf("recv failed with error: %d\n", WSAGetLastError());} while (iResult > 0);// 6) **** When the client application is done receiving data, the closesocket function is called to close the socket// cleanupclosesocket(ConnectSocket);WSACleanup();return 0;}

Named pipes area simple way for two processes to exchange messages.

Mailslots, on the other hand, are a simple way for a process to broadcast messages to multiple processes. One important consideration is that mailslots broadcast messages using datagrams. Adatagram is a small packet of information that the network sends along the wire.

To send messages that are larger than 424 bytes between computers, use named pipes or Windows Sockets instead.


Useful MSDN linkage:

GettingStarted with Winsock

WinsockClient and Server Code Sample

0 0