【小沐学python】开发环境(一)
【小沐学python】socket网络通信(二)
C++实现socket通信(windows)
- 1、简介
- 2、TCP方式
- 2.1 服务端
- 2.2 客户端
- 3、UDP方式
- 3.1 接收端
- 3.2 发送端
- 4、HTTP
- 后续
socket顾名思义就是套接字的意思,用于描述地址和端口,是一个通信链的句柄。应用程序通过socket向网络发出请求或者回应。
socket编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW),前两者较常用。基于TCP的socket编程是流式套接字。
2、TCP方式- Server
- Initialize Winsock.
- Create a socket.
- Bind the socket.
- Listen on the socket for a client.
- Accept a connection from a client.
- Receive and send data.
- Disconnect.
- Client
- Initialize Winsock.
- Create a socket.
- Connect to the server.
- Send and receive data.
- Disconnect.
#include2.2 客户端#include #include #include #pragma comment(lib, "Ws2_32.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" int __cdecl main(void) { WSADATA wsaData; SOCKET ListenSocket = INVALID_SOCKET, ClientSocket = INVALID_SOCKET; struct addrinfo *result = NULL, hints; char recvbuf[DEFAULT_BUFLEN]; int iResult, iSendResult; int recvbuflen = DEFAULT_BUFLEN; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", 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 server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if ( iResult != 0 ) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } // Create a SOCKET for connecting to server ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { printf("socket failed: %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // Setup the TCP listening socket iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("bind failed: %dn", WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("listen failed: %dn", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // Accept a client socket ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("accept failed: %dn", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // No longer need server socket closesocket(ListenSocket); // Receive until the peer shuts down the connection do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { printf("Bytes received: %dn", iResult); // Echo the buffer back to the sender iSendResult = send( ClientSocket, recvbuf, iResult, 0 ); if (iSendResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } printf("Bytes sent: %dn", iSendResult); } else if (iResult == 0) printf("Connection closing...n"); else { printf("recv failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } } while (iResult > 0); // shutdown the connection since we're done iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } // cleanup closesocket(ClientSocket); WSACleanup(); return 0; }
#include3、UDP方式 3.1 接收端#include #include #include #pragma comment(lib, "Ws2_32.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" int __cdecl 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 iResult; int recvbuflen = DEFAULT_BUFLEN; // Validate the parameters if (argc != 2) { printf("usage: %s server-namen", argv[0]); return 1; } // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", 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 port iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result); if ( iResult != 0 ) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } // Attempt to connect to an address until one succeeds for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { // Create a SOCKET for connecting to server ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // 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; } // Send an initial buffer iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 ); if (iResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent: %ldn", iResult); // shutdown the connection since no more data will be sent iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } // Receive until the peer closes the connection do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if ( iResult > 0 ) printf("Bytes received: %dn", iResult); else if ( iResult == 0 ) printf("Connection closedn"); else printf("recv failed: %dn", WSAGetLastError()); } while( iResult > 0 ); // cleanup closesocket(ConnectSocket); WSACleanup(); return 0; }
#include3.2 发送端#include "winsock2.h" #pragma comment(lib, "Ws2_32.lib") void main() { WSADATA wsaData; SOCKET RecvSocket; sockaddr_in RecvAddr; int Port = 27015; char RecvBuf[1024]; int BufLen = 1024; sockaddr_in SenderAddr; int SenderAddrSize = sizeof(SenderAddr); //----------------------------------------------- // Initialize Winsock WSAStartup(MAKEWORD(2,2), &wsaData); //----------------------------------------------- // Create a receiver socket to receive datagrams RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //----------------------------------------------- // Bind the socket to any address and the specified port. RecvAddr.sin_family = AF_INET; RecvAddr.sin_port = htons(Port); RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr)); //----------------------------------------------- // Call the recvfrom function to receive datagrams // on the bound socket. printf("Receiving datagrams...n"); recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize); //----------------------------------------------- // Close the socket when finished receiving datagrams printf("Finished receiving. Closing socket.n"); closesocket(RecvSocket); //----------------------------------------------- // Clean up and exit. printf("Exiting.n"); WSACleanup(); return; }
#include4、HTTP#include "winsock2.h" #pragma comment(lib, "Ws2_32.lib") void main() { WSADATA wsaData; SOCKET SendSocket; sockaddr_in RecvAddr; int Port = 27015; char SendBuf[1024]; int BufLen = 1024; //--------------------------------------------- // Initialize Winsock WSAStartup(MAKEWORD(2,2), &wsaData); //--------------------------------------------- // Create a socket for sending data SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //--------------------------------------------- // Set up the RecvAddr structure with the IP address of // the receiver (in this example case "123.456.789.1") // and the specified port number. RecvAddr.sin_family = AF_INET; RecvAddr.sin_port = htons(Port); RecvAddr.sin_addr.s_addr = inet_addr("123.456.789.1"); //--------------------------------------------- // Send a datagram to the receiver printf("Sending a datagram to the receiver...n"); sendto(SendSocket, SendBuf, BufLen, 0, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr)); //--------------------------------------------- // When the application is finished sending, close the socket. printf("Finished sending. Closing socket.n"); closesocket(SendSocket); //--------------------------------------------- // Clean up and quit. printf("Exiting.n"); WSACleanup(); return; }
无论是Http还是Https都是基于TCP进行传输的,因此使用SOCKET模拟HTTP访问web站点的方式,就是将头部数据拼接成数据包,发送给服务端,然后接收返回再解析就可以了。
这里通过socket访问如下网易新闻api接口网址获取对应数据:
http://data.live.126.net/livechannel/classifylist.json
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include后续#include #include #include #include #pragma comment(lib, "Ws2_32.lib") #define DEFAULT_BUFLEN 4086 #define DEFAULT_PORT 80 #define DEFAULT_URL "/livechannel/classifylist.json" #define DEFAULT_DOMAIN "data.live.126.net" void get_ip_addr(const char *domain, char *ip_addr) { struct hostent *host = gethostbyname(domain); if (!host) { ip_addr = NULL; return; } for (int i = 0; host->h_addr_list[i]; i++) { strcpy(ip_addr, inet_ntoa(*(struct in_addr*) host->h_addr_list[i])); break; } } int __cdecl main(int argc, char **argv) { WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; const char *sendbuf = "this is a test"; char recvbuf[DEFAULT_BUFLEN]; int iResult; int recvbuflen = DEFAULT_BUFLEN; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", iResult); return 1; } char szRemoteIPAddr[128]; get_ip_addr(DEFAULT_DOMAIN, szRemoteIPAddr); // Create a SOCKET for connecting to server ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); WSACleanup(); return 1; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(DEFAULT_PORT); serverAddr.sin_addr.s_addr = inet_addr(szRemoteIPAddr); // Connect to server. iResult = connect(ConnectSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; return 1; } // Send an initial buffer std::string head = "GET " DEFAULT_URL " HTTP/1.1rn"; head.append("Host: " DEFAULT_DOMAIN "rn");//请求的域名 head.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8rn"); head.append("User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36rn"); head.append("Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3rn"); head.append("Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7"); head.append("Accept-Encoding: gzip,deflatern"); head.append("rn");//表明请求头结束了 iResult = send(ConnectSocket, head.c_str(), (int)head.size(), 0); if (iResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent: %ldn", iResult); // Receive until the peer closes the connection do { memset(recvbuf, 0, sizeof(recvbuf)); iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { printf("Bytes received: %dn", iResult); printf(recvbuf); } else if (iResult == 0) printf("Connection closedn"); else printf("recv failed: %dn", WSAGetLastError()); } while (iResult > 0); // cleanup closesocket(ConnectSocket); WSACleanup(); return 0; }
如果你觉得该方法或代码有一点点用处,可以给作者点个赞;╮( ̄▽ ̄)╭
如果你感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
谢谢各位童鞋们啦( ´ ▽´ )ノ ( ´ ▽´)っ!!!



