因为我的毕业设计要用到网络,一开始我就打算做 IOCP Server,我想用最好的方法去实现,结果发现啃不动,于是就从这个示例程序开始吧!
客户端代码:
/* * 文件:简单示例(客户端) * 说明:项目中需包含 Ws2_32.lib,或使用 #pragma once */ #include <stdio.h> #include <WinSock2.h> #define LENGTH 128 #define PORT_NUM 8086 #define EXIT_WITH_MESSAGE(content) \ do \ { \ WSACleanup(); \ printf_s(content); \ system("pause"); \ return EXIT_FAILURE; \ } \ while (FALSE); int main() { int ret, len; WORD wVersion; // 网络传输版本 WSADATA wsaData; // WSADATA char msg[LENGTH]; struct sockaddr_in server; // 服务器信息 SOCKET sockClient = INVALID_SOCKET; // 待创建的套接字 wVersion = MAKEWORD(2, 2); ret = WSAStartup(wVersion, &wsaData); // 初始化 WinSock DLL if (ret != 0) { // 告诉用户不能获取可用的 WinSock DLL EXIT_WITH_MESSAGE("WSAStartup Failed, cannot find a usable winsock dll!\n"); } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { // 告诉用户版本不正确 EXIT_WITH_MESSAGE("Error version!\n"); } sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == sockClient) { // 套接字创建失败 EXIT_WITH_MESSAGE("Invalid socket!\n"); } server.sin_family = AF_INET; server.sin_port = htons(PORT_NUM); server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); ret = connect(sockClient, (struct sockaddr *)&server, sizeof(struct sockaddr)); if (SOCKET_ERROR == ret) { // 连接失败 closesocket(sockClient); EXIT_WITH_MESSAGE("Connect failed!\n"); } do { printf_s("Input a message to send (Note: Length < 128): "); gets_s(msg, LENGTH); // send 函数将会把消息发送到已连接的套接字上,而 sendto 则是发送到指定套接字上 len = strlen(msg) + 1; ret = send(sockClient, msg, len, 0); if (ret < 0 || ret > len) { // 发送有误 closesocket(sockClient); EXIT_WITH_MESSAGE("Send message error!\n"); } if (strcmp(msg, "Quit") == 0) break; memset(msg, 0, LENGTH); ret = recv(sockClient, msg, LENGTH, 0); if (SOCKET_ERROR == ret) { // 接受有误 closesocket(sockClient); EXIT_WITH_MESSAGE("Receive message error!\n"); } else if (0 == ret) { // 连接断开 closesocket(sockClient); EXIT_WITH_MESSAGE("The connection closed!\n"); } printf_s("Client reply: %s\n", msg); } while (strcmp(msg, "Quit")); printf_s("Exit connection!\n"); closesocket(sockClient); WSACleanup(); system("pause"); return EXIT_SUCCESS; }
服务器端代码:
/* * 文件:简单示例(服务器端) * 说明:项目中需包含 Ws2_32.lib,或使用 #pragma once */ #include <stdio.h> #include <WinSock2.h> #define LENGTH 128 #define PORT_NUM 8086 #define EXIT_WITH_MESSAGE(content) \ do \ { \ WSACleanup(); \ printf_s(content); \ system("pause"); \ return EXIT_FAILURE; \ } \ while (FALSE); int main() { int ret, len; WORD wVersion; // 网络传输版本 WSADATA wsaData; // WSADATA char msg[LENGTH]; struct sockaddr_in server, client; // 服务器信息,客户端信息 SOCKET sockServer = INVALID_SOCKET, sockListener = INVALID_SOCKET; // 服务器套接字,监听套接字 wVersion = MAKEWORD(2, 2); ret = WSAStartup(wVersion, &wsaData); // 初始化 WinSock DLL if (ret != 0) { // 告诉用户不能获取可用的 WinSock DLL EXIT_WITH_MESSAGE("WSAStartup Failed, cannot find a usable winsock dll!\n"); } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { // 告诉用户版本不正确 EXIT_WITH_MESSAGE("Error version!\n"); } sockListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == sockListener) { // 套接字创建失败 EXIT_WITH_MESSAGE("Invalid listener socket!\n"); } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(PORT_NUM); ret = bind(sockListener, (struct sockaddr *)&server, sizeof(struct sockaddr_in)); if (SOCKET_ERROR == ret) { // 绑定端口失败 closesocket(sockListener); EXIT_WITH_MESSAGE("Bind error!\n"); } ret = listen(sockListener, SOMAXCONN); if (SOCKET_ERROR == ret) { // 监听失败 closesocket(sockListener); EXIT_WITH_MESSAGE("Listen error!\n"); } len = sizeof(struct sockaddr_in); sockServer = accept(sockListener, (struct sockaddr*)&client, &len); if (INVALID_SOCKET == sockServer) { // 接收失败 closesocket(sockListener); EXIT_WITH_MESSAGE("Accept error!\n"); } do { memset(msg, 0, LENGTH); ret = recv(sockServer, msg, LENGTH, 0); if (SOCKET_ERROR == ret) { // 接受有误 closesocket(sockServer); EXIT_WITH_MESSAGE("Receive message error!\n"); } else if (0 == ret) { // 连接断开 closesocket(sockServer); EXIT_WITH_MESSAGE("The connection closed!\n"); } printf_s("Client: %s\n", msg); strcpy_s(msg, LENGTH, "SweetLover has received your letter, he'll reply soon!"); len = strlen(msg) + 1; ret = send(sockServer, msg, len, 0); if (ret <= 0 || ret > len) { // 发送有误 closesocket(sockServer); EXIT_WITH_MESSAGE("Send message error!\n"); } } while (TRUE); printf_s("Exit connection!\n"); closesocket(sockServer); closesocket(sockListener); WSACleanup(); system("pause"); return EXIT_SUCCESS; }
总结:
1.网络连接的步骤:http://blog.csdn.net/wwqingyue/article/details/8792608
UDP和TCP编程步骤也有些不同,如下:
TCP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt(); * 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、开启监听,用函数listen();
5、接收客户端上来的连接,用函数accept();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
8、关闭监听;
TCP编程的客户端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置要连接的对方的IP地址和端口等属性;
5、连接服务器,用函数connect();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
与之对应的UDP编程步骤要简单许多,分别如下:
UDP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、循环接收数据,用函数recvfrom(); 5、关闭网络连接;
UDP编程的客户端一般步骤是:
1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 4、设置对方的IP地址和端口等属性; 5、发送数据,用函数sendto(); 6、关闭网络连接;
2.套接字编程原理:http://www.cnblogs.com/haoyuanyuan/p/3268351.html
3.常用术语概念:http://www.vckbase.com/index.php/wv/300
socket 通信关于bind那点事