基于visual c++之windows核心编程代码分析(10)实现socket通信
来源:互联网 发布:vscode github 编辑:程序博客网 时间:2024/06/13 03:53
在多台计算机之间实现通信,最常见的方法有两种:Socket通信与UDP通信。Socket是一种基于TCP/IP协议,建立稳定连接的点对点通信,它的特点是安全性高,数据不会丢失,但是很占系统资源。在JAVA中,ServerSocket类和Socket类为我们实现了Socket通信,建立通信的一般步骤是:1。建立服务器ServerSocket ss = new ServerSocket(端口号);Socket socket = ss.accept();这样,我们就已经建立了服务器,其中accept()方法会阻塞,知道有客户发送一个连接请求,我们可以通过socket.getInputStream()和socket.getOutputStream()来获得输入输出流,如调用socket.getInputStream()获得一个输入流,实际上这个流就是连接对方的一个输出流,流的操作与文件流操作相同,我们可以用操作文件的方法来操作它们。2。建立客户端Socket socket = new Socket(主机名,端口号)客户端只需这一句代码就可以与服务器取得连接,这里的主机名应为服务器的IP地址,端口号是服务器用来监听该程序的端口,同样可以通过socket.getInputStream()和socket.getOutputStream()来获得输入输出流。在以上程序中,已经实现了一个最简单的客户端和服务器的通信。但是,还有一些问题。首先,这个通信只执行一次,程序就将结束。因为我们只读了一次输入流,如果想要建立客户与服务器之间的稳定的会话,就要用到多线程:Thread thread = new Thread(new Sender());thread.start();InputStream input = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(input));
while(true){
br.readLine();
}
其中,Sender是一个实现了Runnable接口的类,用它来专门负责发送数据,主线程只需要不听地接受数据就行。Sender类中的run()方法应该具有以下代码:
PrintWriter pw = new PrintWriter(socket.getOutputStream());
while(true){
pw.println(数据);
}
即使按上面的方式做了,程序还是有问题,因为它只能在一个时间内为一个客户服务,不能同时为多个客户服务,如多要想同时为多个客户服务,服务器应具有类似以下的代码:
ServerSocker ss = new ServerSocker(端口号);
socket = null;
while(true){
socket = ss.accept();
Thread thread1 = new Thread(new Sender());
thread1.start();
Thread thread2 = new Thread(new Receiver());
thread2.start();
}
在这里,新开启了2个线程分别负责接收和发送。Receiver是一个与Sender非常相似的类,它主要用来接收数据。在客户端,我们同样应开启2个线程:
Socket socket = new Socket(服务器IP,端口号);
Sender sender = new Sender(socket);
Thread thread1 = new Thread(sender);
thread1.start();
Receiver receiver = new Receiver(socket);
Thread thread2 = new Thread(receiver);
thread2.start();
我们来亲自动手实现案例
实现客户端
-
- #include <stdio.h>
- #include "winsock2.h"
-
- #define RECV_BUFFER_SIZE 8192
-
-
-
-
-
- void main(int argc, char* argv[])
- {
-
- SOCKADDR_IN clientService;
- SOCKET ConnectSocket;
- WSADATA wsaData;
- LPVOID recvbuf;
- int bytesSent;
- int bytesRecv = 0;
- char sendbuf[32] = "get information";
-
-
- int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
- if (iResult != NO_ERROR)
- printf("Error at WSAStartup()\n");
-
-
- ConnectSocket = socket(AF_INET,
- SOCK_STREAM,
- IPPROTO_TCP
- );
- if (ConnectSocket == INVALID_SOCKET)
- {
- printf("Error at socket(): %ld\n", WSAGetLastError());
- WSACleanup();
- return;
- }
-
-
- clientService.sin_family = AF_INET;
- clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
- clientService.sin_port = htons( 10000 );
-
-
- if ( connect(
- ConnectSocket,
- (SOCKADDR*) &clientService,
- sizeof(clientService)
- ) == SOCKET_ERROR)
- {
- printf( "Failed to connect(%d)\n",WSAGetLastError() );
- WSACleanup();
- return;
- }
-
-
- if(argc ==2 && (!lstrcmp(argv[1], "-d")))
- {
- lstrcpyn(sendbuf, "download file", 32);
- }
-
- bytesSent = send( ConnectSocket,
- sendbuf,
- lstrlen(sendbuf)+1,
- 0 );
-
- if(bytesSent == SOCKET_ERROR)
- {
- printf( "send error (%d)\n", WSAGetLastError());
- closesocket(ConnectSocket);
- return;
- }
- printf( "Bytes Sent: %ld\n", bytesSent );
-
-
- recvbuf = HeapAlloc(GetProcessHeap(), 0, RECV_BUFFER_SIZE);
-
- while( bytesRecv != SOCKET_ERROR )
- {
-
- bytesRecv = recv( ConnectSocket,
- recvbuf,
- RECV_BUFFER_SIZE,
- 0 );
- if ( bytesRecv == 0 )
- {
- printf( "Connection Closed.\n");
- break;
- }
-
- printf( "Bytes Recv: %ld\n", bytesRecv );
- }
- HeapFree(GetProcessHeap(), 0, recvbuf);
- WSACleanup();
- return;
- }
实现服务端
-
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <stdio.h>
-
- #define DEFAULT_PORT "10000" // 端口
- #define MAX_REQUEST 1024 // 接收数据的缓存大小
- #define BUF_SIZE 4096 // 发送数据的缓存大小
-
-
-
-
-
-
-
-
- DWORD WINAPI CommunicationThread(
- LPVOID lpParameter
- )
- {
- DWORD dwTid = GetCurrentThreadId();
-
- SOCKET socket = (SOCKET)lpParameter;
-
- LPSTR szRequest = HeapAlloc(GetProcessHeap(),0, MAX_REQUEST);
- int iResult;
- int bytesSent;
-
-
- iResult = recv(socket,
- szRequest,
- MAX_REQUEST,
- 0);
- if (iResult == 0)
- {
- printf("Connection closing...\n");
- HeapFree(GetProcessHeap(), 0 ,szRequest);
- closesocket(socket);
- return 1;
- }
- else if (iResult == SOCKET_ERROR)
- {
- printf("recv failed: %d\n", WSAGetLastError());
- HeapFree(GetProcessHeap(), 0 ,szRequest);
- closesocket(socket);
- return 1;
- }
- else if (iResult > 0)
- {
-
- printf("\tCommunicationThread(%d)\tBytes received: %d\n", dwTid, iResult);
- printf("\tCommunicationThread(%d)\trequest string is (%s)\n",dwTid, szRequest);
-
-
- if (lstrcmpi(szRequest, "download file") == 0)
- {
-
- HANDLE hFile;
- LPVOID lpReadBuf;
- DWORD dwBytesRead;
- DWORD dwFileSize;
- DWORD dwSendFile = 0;
- hFile = CreateFile("download.txt",
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE)
- {
- printf("\tCommunicationThread\tCould not open file (error %d)\n",
- GetLastError());
- send(socket, "error", 6, 0);
- closesocket(socket);
- return 1;
- }
-
- lpReadBuf = HeapAlloc(GetProcessHeap(), 0 , BUF_SIZE);
-
- dwFileSize = GetFileSize(hFile, NULL);
-
- while(1)
- {
-
- if(!ReadFile(hFile, lpReadBuf, BUF_SIZE, &dwBytesRead, NULL))
- {
- printf("\tCommunicationThread\tCould not read from file (error %d)\n",
- GetLastError());
- closesocket(socket);
- CloseHandle(hFile);
- return 1;
- }
-
- bytesSent = send(socket, lpReadBuf, dwBytesRead, 0);
- if( bytesSent == SOCKET_ERROR)
- {
- printf("\tCommunicationThread\tsend error %d\n",
- WSAGetLastError());
- closesocket(socket);
- CloseHandle(hFile);
- return 1;
- }
-
- printf("\tCommunicationThread(%d)\tsend %d bytes\n", dwTid, bytesSent);
-
- dwSendFile += dwBytesRead;
-
- if(dwSendFile == dwFileSize)
- {
- printf("\tCommunicationThread\tFile download ok\n");
- break;
- }
- }
-
- HeapFree(GetProcessHeap(), 0 , lpReadBuf);
- CloseHandle(hFile);
- closesocket(socket);
- }
-
- else if (lstrcmpi(szRequest, "get information") == 0)
- {
-
- bytesSent = send(socket,
- "this is information",
- lstrlen("this is information")+1,
- 0);
-
- if( bytesSent == SOCKET_ERROR)
- {
- printf("\tCommunicationThread\tsend error %d\n",
- WSAGetLastError());
- closesocket(socket);
- return 1;
- }
- printf("\tCommunicationThread(%d)\tsend %d bytes\n",dwTid, bytesSent);
- }
- else
- {
- printf ("unreferenced request\n");
- }
- }
-
- HeapFree(GetProcessHeap(), 0 ,szRequest);
- closesocket(socket);
- return 0;
- }
-
-
-
-
-
- int __cdecl main(void)
- {
- WSADATA wsaData;
- SOCKET ListenSocket = INVALID_SOCKET;
- SOCKET ClientSocket = INVALID_SOCKET;
- struct addrinfo *result = NULL,
- hints;
- int iResult;
-
-
- 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;
-
-
- iResult = getaddrinfo(NULL,
- DEFAULT_PORT,
- &hints,
- &result);
- if ( iResult != 0 )
- {
- printf("getaddrinfo failed: %d\n", iResult);
- WSACleanup();
- return 1;
- }
-
-
- ListenSocket = socket(
- result->ai_family,
- result->ai_socktype,
- result->ai_protocol);
- if (ListenSocket == INVALID_SOCKET)
- {
- printf("socket failed: %ld\n", WSAGetLastError());
- freeaddrinfo(result);
- WSACleanup();
- return 1;
- }
-
- iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
- if (iResult == SOCKET_ERROR)
- {
- printf("bind failed: %d\n", WSAGetLastError());
- freeaddrinfo(result);
- closesocket(ListenSocket);
- WSACleanup();
- return 1;
- }
- printf("bind\n");
-
- freeaddrinfo(result);
-
-
- iResult = listen(ListenSocket, SOMAXCONN);
- printf("start listen......\n");
- if (iResult == SOCKET_ERROR)
- {
- printf("listen failed: %d\n", WSAGetLastError());
- closesocket(ListenSocket);
- WSACleanup();
- return 1;
- }
- while (1)
- {
-
- printf("ready to accept\n");
- ClientSocket = accept(ListenSocket, NULL, NULL);
-
-
- printf("accept a connetion\n");
- if (ClientSocket == INVALID_SOCKET)
- {
- printf("accept failed: %d\n", WSAGetLastError());
- closesocket(ListenSocket);
- break;
- }
-
-
- if(!CreateThread(
- NULL,
- 0,
- CommunicationThread,
- (LPVOID)ClientSocket,
- 0,
- NULL))
- {
- printf("Create Thread error (%d)", GetLastError());
- break;
- }
- }
-
- WSACleanup();
- return 0;
- }
-
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <stdio.h>
-
- #define DEFAULT_PORT "10000" // 端口
- #define MAX_REQUEST 1024 // 接收数据的缓存大小
- #define BUF_SIZE 4096 // 发送数据的缓存大小
-
-
-
-
-
-
-
-
- DWORD WINAPI CommunicationThread(
- LPVOID lpParameter
- )
- {
- DWORD dwTid = GetCurrentThreadId();
-
- SOCKET socket = (SOCKET)lpParameter;
-
- LPSTR szRequest = HeapAlloc(GetProcessHeap(),0, MAX_REQUEST);
- int iResult;
- int bytesSent;
-
-
- iResult = recv(socket,
- szRequest,
- MAX_REQUEST,
- 0);
- if (iResult == 0)
- {
- printf("Connection closing...\n");
- HeapFree(GetProcessHeap(), 0 ,szRequest);
- closesocket(socket);
- return 1;
- }
- else if (iResult == SOCKET_ERROR)
- {
- printf("recv failed: %d\n", WSAGetLastError());
- HeapFree(GetProcessHeap(), 0 ,szRequest);
- closesocket(socket);
- return 1;
- }
- else if (iResult > 0)
- {
-
- printf("\tCommunicationThread(%d)\tBytes received: %d\n", dwTid, iResult);
- printf("\tCommunicationThread(%d)\trequest string is (%s)\n",dwTid, szRequest);
-
-
- if (lstrcmpi(szRequest, "download file") == 0)
- {
-
- HANDLE hFile;
- LPVOID lpReadBuf;
- DWORD dwBytesRead;
- DWORD dwFileSize;
- DWORD dwSendFile = 0;
- hFile = CreateFile("download.txt",
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE)
- {
- printf("\tCommunicationThread\tCould not open file (error %d)\n",
- GetLastError());
- send(socket, "error", 6, 0);
- closesocket(socket);
- return 1;
- }
-
- lpReadBuf = HeapAlloc(GetProcessHeap(), 0 , BUF_SIZE);
-
- dwFileSize = GetFileSize(hFile, NULL);
-
- while(1)
- {
-
- if(!ReadFile(hFile, lpReadBuf, BUF_SIZE, &dwBytesRead, NULL))
- {
- printf("\tCommunicationThread\tCould not read from file (error %d)\n",
- GetLastError());
- closesocket(socket);
- CloseHandle(hFile);
- return 1;
- }
-
- bytesSent = send(socket, lpReadBuf, dwBytesRead, 0);
- if( bytesSent == SOCKET_ERROR)
- {
- printf("\tCommunicationThread\tsend error %d\n",
- WSAGetLastError());
- closesocket(socket);
- CloseHandle(hFile);
- return 1;
- }
-
- printf("\tCommunicationThread(%d)\tsend %d bytes\n", dwTid, bytesSent);
-
- dwSendFile += dwBytesRead;
-
- if(dwSendFile == dwFileSize)
- {
- printf("\tCommunicationThread\tFile download ok\n");
- break;
- }
- }
-
- HeapFree(GetProcessHeap(), 0 , lpReadBuf);
- CloseHandle(hFile);
- closesocket(socket);
- }
-
- else if (lstrcmpi(szRequest, "get information") == 0)
- {
-
- bytesSent = send(socket,
- "this is information",
- lstrlen("this is information")+1,
- 0);
-
- if( bytesSent == SOCKET_ERROR)
- {
- printf("\tCommunicationThread\tsend error %d\n",
- WSAGetLastError());
- closesocket(socket);
- return 1;
- }
- printf("\tCommunicationThread(%d)\tsend %d bytes\n",dwTid, bytesSent);
- }
- else
- {
- printf ("unreferenced request\n");
- }
- }
-
- HeapFree(GetProcessHeap(), 0 ,szRequest);
- closesocket(socket);
- return 0;
- }
-
-
-
-
-
- int __cdecl main(void)
- {
- WSADATA wsaData;
- SOCKET ListenSocket = INVALID_SOCKET;
- SOCKET ClientSocket = INVALID_SOCKET;
- struct addrinfo *result = NULL,
- hints;
- int iResult;
-
-
- 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;
-
-
- iResult = getaddrinfo(NULL,
- DEFAULT_PORT,
- &hints,
- &result);
- if ( iResult != 0 )
- {
- printf("getaddrinfo failed: %d\n", iResult);
- WSACleanup();
- return 1;
- }
-
-
- ListenSocket = socket(
- result->ai_family,
- result->ai_socktype,
- result->ai_protocol);
- if (ListenSocket == INVALID_SOCKET)
- {
- printf("socket failed: %ld\n", WSAGetLastError());
- freeaddrinfo(result);
- WSACleanup();
- return 1;
- }
-
- iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
- if (iResult == SOCKET_ERROR)
- {
- printf("bind failed: %d\n", WSAGetLastError());
- freeaddrinfo(result);
- closesocket(ListenSocket);
- WSACleanup();
- return 1;
- }
- printf("bind\n");
-
- freeaddrinfo(result);
-
-
- iResult = listen(ListenSocket, SOMAXCONN);
- printf("start listen......\n");
- if (iResult == SOCKET_ERROR)
- {
- printf("listen failed: %d\n", WSAGetLastError());
- closesocket(ListenSocket);
- WSACleanup();
- return 1;
- }
- while (1)
- {
-
- printf("ready to accept\n");
- ClientSocket = accept(ListenSocket, NULL, NULL);
-
-
- printf("accept a connetion\n");
- if (ClientSocket == INVALID_SOCKET)
- {
- printf("accept failed: %d\n", WSAGetLastError());
- closesocket(ListenSocket);
- break;
- }
-
-
- if(!CreateThread(
- NULL,
- 0,
- CommunicationThread,
- (LPVOID)ClientSocket,
- 0,
- NULL))
- {
- printf("Create Thread error (%d)", GetLastError());
- break;
- }
- }
-
- WSACleanup();
- return 0;
- }
0 0