博客
关于我
windows网络编程 | 基于控制台的简单服务器/客户端程序(5.4小节随书案例)
阅读量:286 次
发布时间:2019-03-01

本文共 6780 字,大约阅读时间需要 22 分钟。

基于流式套接字的回射程序开发

5.4 编程举例

本节通过一个Windows控制台应用程序实现基于流式套接字的回射功能。回射是指服务器接收客户发来的字符,并将接收到的内容再次发送回客户端,以检测网络和主机运行状态。本节设计客户和服务器两个独立的网络应用程序,结合网络操作的基本步骤讲述流式套接字编程中各函数的使用方法。

5.4.1 基于流式套接字的回射客户端编程操作

客户端程序接收命令行参数argv[1]传入的服务器端地址,与服务器进行连接。Visual Studio编译器设置命令行参数方法:项目(右键)属性——》调试——》命令参数。

客户端完整代码:

#define WIN32_LEAN_AND_MEAN#include 
#include
#include
#include
#include
#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 __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; if (argc != 2) { printf("usage: %s server-name\n", argv[0]); return 1; } iResult = 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; iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); return 1; } for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { ConnectSocket = 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; } 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; } iResult = 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); iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed with error: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { printf("Bytes received: %d\n", iResult); } else if (iResult == 0) { printf("Connection closed\n"); } else { printf("recv failed with error: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } } while (iResult > 0); closesocket(ConnectSocket); WSACleanup(); return 0;}

5.4.2 基于流式套接字的回射服务器端编程操作

服务器端完整代码:

#undef UNICODE#define WIN32_LEAN_AND_MEAN#include 
#include
#include
#include
#include
#pragma comment (lib, "Ws2_32.lib")#define DEFAULT_BUFLEN 512#define DEFAULT_PORT "27015"int __cdecl main(void) { WSADATA wsaData; int iResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; struct addrinfo *result = NULL; struct addrinfo hints; int iSendResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed with error: %d\n", iResult); return 1; } ZeroMemory(&hints, sizeof(hints)); hints.aifamily = AF_INET; hints.aisocktype = SOCK_STREAM; hints.aiprotocol = IPPROTO_TCP; hints.aiflags = AI_PASSIVE; iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); return 1; } ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { printf("socket failed with error: %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 with error: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("listen failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("accept failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } closesocket(ListenSocket); do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { printf("Bytes received: %d\n", iResult); iSendResult = 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); iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed with error: %d\n", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } closesocket(ClientSocket); WSACleanup(); return 0;}

运行实例

运行环境:Visual Studio 2019,Windows 10专业版。

1. 创建解决方案

新建工程,并创建两个项目,分别用于编写服务器端和客户端的程序。将上述代码写入各自的.cpp文件中。

2. 客户端设置

设置客户端命令行参数:鼠标右键cli项目——》属性,选择调试,在命令参数中输入服务器IP地址。由于是本地测试,这里使用本地环回地址127.0.0.1

3. 多项目启动设置

由于需要同时运行服务器和客户端两个程序,这里设置编译器为多项目启动方式。

3.1 设置多项目启动

右键解决方案——》属性,选择通用属性——》启动项目——》多个启动项目,将sercli都设置为启动。

3.2 设置启动顺序

在项目依赖项中选择cli项目依赖于ser

4. 启动运行

点击运行,运行结果如图所示。

转载地址:http://deio.baihongyu.com/

你可能感兴趣的文章
node环境下使用import引入外部文件出错
查看>>
node环境:Error listen EADDRINUSE :::3000
查看>>
Node的Web应用框架Express的简介与搭建HelloWorld
查看>>
Node第一天
查看>>
node编译程序内存溢出
查看>>
Node读取并输出txt文件内容
查看>>
node防xss攻击插件
查看>>
noi 1996 登山
查看>>
noi 7827 质数的和与积
查看>>
NOI-1.3-11-计算浮点数相除的余数
查看>>
noi.ac #36 模拟
查看>>
NOI2010 海拔(平面图最大流)
查看>>
NOIp2005 过河
查看>>
NOIP2011T1 数字反转
查看>>
NOIP2014 提高组 Day2——寻找道路
查看>>
noip借教室 题解
查看>>
NOIP模拟测试19
查看>>
NOIp模拟赛二十九
查看>>
Vue3+element plus+sortablejs实现table列表拖拽
查看>>
Nokia5233手机和我装的几个symbian V5手机软件
查看>>