首先,网上很多博客会给出TCP/IP客户端和服务器端的代码,然而只是将代码简单地复制到项目中并不知道如何使用,本篇博客介绍了一下详细过程。代码完全来自《TCP/IP网络编程》(韩 尹圣雨)这本书,我也刚开始学,代码细节完全不懂,只是敲了一遍,能跑通程序而已。
1. 环境:1台电脑(能上网)、Windows操作系统(我的是Win10)、Visual Studio(我的是VS2019)
2. 步骤:
2.1 使用VS创建一个新项目文件夹,我的项目名称为Practice
2.2 新建项目完毕后解决方案资源管理器这一栏有一个和项目文件夹同名的项目,将其改名为 Server(仅仅只是为了方便叙述),Server是服务器的意思;
然后在 解决方案“Practice"(1个项目) 上右击 -- 添加 -- 新建项目,同样新建一个空项目,取名为”Client“,新建完毕后如下图:
2.3 (必不可少的一步,虽然我也不知道有什么用)在Server和Client两个项目上 务必都要右击 -- 属性 -- 链接器 -- 输入,然后在“附加依赖项”这一栏右侧点击下三角 -- 编辑,在最上方空白处输入 ws2_32.lib ,然后一直点击 确定 即可,如下图:
2.4 在两个项目的 源文件上右击 -- 添加 -- 新建项来给两个项目添加两个cpp文件,命名与书上一致,Server项目下的cpp文件命名为 “hello_server_win”,Client项目下的cpp文件命名为“hello_client_win”,如下图:
然后分别添加代码如下:(直接从书上抄下来的)
hello_server_win.cpp:
//hello_server_win.cpp
#include<stdio.h>
#include<stdlib.h>
#include<WinSock2.h>
void ErrorHandling(const char* message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hServSock, hClntSock;
SOCKADDR_IN servAddr, clntAddr;
int szClntAddr;
char message[] = "Hello World!";
if (argc != 2)
{
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hServSock = socket(PF_INET, SOCK_STREAM, 0);
if (hServSock == INVALID_SOCKET)
ErrorHandling("socket() error");
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(atoi(argv[1]));
if (bind(hServSock, (SOCKADDR*) &servAddr, sizeof(servAddr)) == SOCKET_ERROR)
ErrorHandling("bind() error");
if (listen(hServSock, 5) == SOCKET_ERROR)
ErrorHandling("listen() error");
szClntAddr = sizeof(clntAddr);
hClntSock = accept(hServSock, (SOCKADDR*) &clntAddr, &szClntAddr);
if (hClntSock == INVALID_SOCKET)
ErrorHandling("accept() error");
send(hClntSock, message, sizeof(message), 0);
closesocket(hClntSock);
closesocket(hServSock);
WSACleanup();
return 0;
}
void ErrorHandling(const char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
hello_client_win.cpp
//hello_client_win.cpp
#include<stdio.h>
#include<stdlib.h>
#include<WinSock2.h>
void ErrorHandling(const char* message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN servAddr;
char message[30];
int strLen;
if (argc != 3)
{
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET)
ErrorHandling("socket() error");
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(argv[1]);
servAddr.sin_port = htons(atoi(argv[2]));
if (connect(hSocket, (SOCKADDR*) &servAddr, sizeof(servAddr)) == SOCKET_ERROR)
ErrorHandling("connect() error!");
strLen = recv(hSocket, message, sizeof(message) - 1, 0);
if (strLen == -1)
ErrorHandling("read() error!");
printf("Message from server: %s \n", message);
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(const char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
2.5 (必不可少的一步)在Client项目上右击 -- 属性 -- C/C++ -- 常规 -- SDL检查,选择“否”,然后确定,如图:
2.6 按F7编译,经过以上操作以后应该不会报错了,在Practice项目文件夹下会生成一个名为Debug的文件夹,点击进去,会发现有两个分别名为“Server.exe”和“Client.exe”的可执行文件,如下图:
3. 以上都没有问题的情况下,打开两个命令行(Win + R,然后输入cmd,再按回车),它们稍后将分别作为服务器和客户端,在两个命令行都切换到自己的Debug目录下(命令行输入:cd + 空格 + 路径,再按回车)
在其中一个命令行输入:"Server 9190",然后按回车,如下图。这句话的作用是运行Server.exe,端口号为9190(端口号是自己设置的,可为1024-65535之间的任意值),按下回车后会该服务器会等待客户端连入。期间如果有什么Windows防火墙已阻止此应用的部分功能之类的提示,直接“确定”或者“允许访问”即可
接着在另一个命令行输入“Client 127.0.0.1 9190”,然后按回车。这句话的作用是运行客户端,访问127.0.0.1这个IP地址(这是自己主机的IP地址),端口号为9190(必须与Server的端口号一致才能通信)。按下回车后该窗口(即客户端Client)会收到服务器端(即Server)发送的“ Hello World!”,通信完毕
最后,希望这篇博客能帮助到像我一样刚开始学TCP/IP网络编程的小白