概要
最近在做网络编程的时候遇到了亿点点困难,主要实现目标是:
- 打开浏览器,输入http://主机IP地址:8080,浏览器上显示主页(html文件)。
- 能够控制用户是否能访问http://主机IP地址:8080内容
一、使用socket来做一个小型的服务器,主要的步骤如下所示:
- 导入主要的头文件
- 创建并加载一个网络库,然后对其设置版本号
- 创建服务器端的SOCKET对象,然后配置并绑定其IP地址、端口号、填充字节(这是啥我也不懂哈哈哈哈)、协议族
- 设置服务器端口进行监听,以及设置最大连接数量
- 创建客户机SOCKET对象,等待连接该客户机对象和服务端对象
- 连接成功后,先接收网页那边发来的请求报头,然后就能把我们的网页文件上传过去显示了
- 每次发送过去之后就关闭该客户机的连接,因为这是短连接
二、使用pthread多线程对socket服务器进行控制
- 导入主要的头文件
- 定义一个全局的flag用来判断当前是否允许客户机和服务器进行连接
- 创建一个子线程用于控制这个flag的变化
- 创建一个子线程用于显示一些必要的提示信息
- 修改客户机连接服务器的条件使其受flag控制
细述
1、首先,要使用socket进行编程,需要引入基本的头文件:WinSock2.h,还有winsock2的静态库文件ws2_32.lib
#include <iostream>
#include <stdio.h>
#include <WinSock2.h> // socket的头文件
//连接winsock2.h的静态库文件
#pragma comment(lib, "ws2_32.lib")
2、在main函数里面定义WSADATA,然后设置版本号
// 加载网络库
WSADATA wsaData;
// 设置版本号
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "网络库加载失败" << endl;
return 0;
}
3、创建服务器端的SOCKET对象,然后配置并绑定其IP地址、端口号、填充字节(这是啥我也不懂哈哈哈哈)、协议族
// 创建服务器端的socket,里面有三个参数,第一个是协议族的类型,第二个是STREAM类型的套接字,第三个是TCP
// 细节可以看看https://blog.csdn.net/mabin2005/article/details/120056945
SOCKET servSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (servSocket == INVALID_SOCKET) {
cout << "socket创建失败!" << endl;
return 0;
}
// 准备配置数据
/*
服务器的socket地址
包含:
1.sin_addr : IP地址
2.sin_port : 端口号
3.sin_zero : 填充字节
4.sin_family : 协议簇
*/
sockaddr_in servAddr;
// 初始化socket地址
memset(&servAddr, 0, sizeof(SOCKADDR));
// 设置使用的协议簇
servAddr.sin_family = AF_INET;
// 设置使用的端口
// htons 把本地字节序转为网络字节序
servAddr.sin_port = htons(8080);
// INADDR_ANY就是0.0.0.0的地址,表示为任意地址
servAddr.sin_addr.s_addr = INADDR_ANY;
// 绑定配置到servSocket上
if (bind(servSocket, (SOCKADDR*)&servAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "绑定失败" << endl;
return 0;
}
4、设置服务器端口进行监听,以及设置最大连接数量
/*
设置监听服务器端口
第二个参数指连接的最大数量
SOMAXCONN 指系统自动选择最合适的连接个数
*/
listen(servSocket, 10);
5、创建客户机SOCKET对象,等待连接该客户机对象和服务端对象
// 为客户机创建对象
sockaddr_in clntAddr;
cout << "等待连接" << endl;
/*
accept函数: `
一共三个参数:
1.SOCKET : 服务端的SOCKET对象,用于判断是否接受连接
2.sockaddr : 接受客户端的IP地址和端口号,然后判断与服务端是否一致
3.int *addrlen : 不知道,暂时
*/
int nSize = sizeof(clntAddr);
SOCKET clientSock = accept(servSocket, (SOCKADDR*)&clntAddr, &nSize);
if (!onFlag) {
closesocket(clientSock);
continue;
}
// 判断是否连接成功
if (clientSock == INVALID_SOCKET) {
cout << "连接失败" << endl;
return 0;
}
cout << "新的一个连接成功" << endl;
6、连接成功后,先接收网页那边发来的请求报头,然后就能把我们的网页文件上传过去显示了
// 处理连接请求
char recvBuf[1024] = "";
if (recv(clientSock, recvBuf, sizeof(recvBuf), 0) <= 0) {
cout << "接收出错" << endl;
break;
}
cout << "接收到数据: " << recvBuf << endl;
// 给客户端发送文本
char filePath[128] = "index.html";
// 发送文件
sendHtml(clientSock, filePath);
发送网页文件的代码如下: