#pragma comment(linker, “/STACK:36777216”)
//#pragma GCC optimize (“O2”)
/**
* This code has been written by YueGuang, feel free to ask me question. Blog: http://www.moonl1ght.xyz
* created:
*/
#define LOCAL
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
//#include
using namespace std;
// un template header
#pragma comment (lib, “ws2_32.lib”)// 链接ws2_32.lib文件
#include //windows socket编程头文件
//自定义头文件
//}/* …………………………………………………………………………………………………………………. */
/*
bug 说明区域
1.颜色设置setcolor还不能使用
*/
/*
变量解释说明区域 QAQ
*/
// 全局常量
const int BUF_SIZE = 2048;
const int SEND_SIZE = 1000;
const int MAX_BUF_SIZE = 500;
const int NICKNAME_LEN = 20;
const int MAX_CLIENT_COUNT = 20;
// 全局变量
SOCKET sockSer, sockCli;
SOCKADDR_IN addrSer, addrCli;// address 地址 客户端地址和服务器地址
int clientCount = 0;
int naddr = sizeof(SOCKADDR_IN);
char sendbuf[BUF_SIZE];
char inputbuf[BUF_SIZE];
char recvbuf[BUF_SIZE];
//特殊变量
struct Client{
SOCKET s;
SOCKADDR_IN sin;
char name[NICKNAME_LEN];
}Cli[MAX_CLIENT_COUNT];
//该结构体的目的是允许多台PC机对服务器进行访问
//全局函数
//服务器接听连接的实现
DWORD WINAPI ServerListeningConnect(LPVOID lp) {
SOCKET *s = (SOCKET*)lp;
int nrecv;
int len = sizeof(SOCKADDR);
(true)
{
Cli[clientCount + 1].s = accept(*s, (SOCKADDR*)&Cli[clientCount + 1].sin, &len);
// 这里不清楚是否是阻塞,因此加上判断
if (Cli[clientCount + 1].s != INVALID_SOCKET)
{
clientCount++;
unsigned long ul = 1;
int ret = ioctlsocket(Cli[clientCount].s, FIONBIO, (unsigned long *)&ul);
if (ret == SOCKET_ERROR) {
printf(“非阻塞化失败!”);
return 0;
}
// 获取客户端的姓名
recv(Cli[clientCount].s, Cli[clientCount].name, SEND_SIZE, 0);
// 反馈。不晓得能反馈到哪
for (int i = 1; i
{
char sendBuf[MAX_BUF_SIZE] = “Welcome [“;
strcat(sendBuf, Cli[i].name);
strcat(sendBuf, “] 加入聊天,当前在线的有”);
char number[50];
itoa(clientCount, number, 50);
strcat(sendBuf, number);
strcat(sendBuf, “人”);
printf(“%sn”, sendBuf);
send(Cli[i].s, sendBuf, SEND_SIZE, 0);
}
}
}
}
using namespace std;
int main(){
//
加载socket函数,载入socket库
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0){
//setColor(COLOR_ERROR);
cout
system(“pause”);
return 0;
}
cout
//创建socket(地址描述(AF_INET格式 – ipv4),指定socket类型(使用的是流式套接字即TCP协议), 指定协议
sockSer = socket(AF_INET, SOCK_STREAM, 0);
//初始化服务器的包结构,也可以称为初始化地址包
// 封装成sockaddr_in 类,俗称地址包,保存端口 和IP地址
SOCKADDR_IN addrSrv;
/*将IP地址 INADDR_ANY (0x00000)主机字节转换成 络字节:高字节在前面
*addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
*使用局域 中的IP 可以打开cmd,输入ipconfig进行查询
*/
char ip[] = “192.168.81.90”;
/*函数获取本地IP的方法如下,但是microsoft visual studio 2013 不具备localipget的功能所以不使用该方法
*getLocalIP(localIP, sizeof(localIP) / sizeof(char));
*setColor(COLOR_INFO);
*/
cout
// inet_addr:将点分十进制的IP 转换成二进制,然后再转换成 络字节
addrSrv.sin_addr.S_un.S_addr = inet_addr(ip);
// 设置为IP协议族
addrSrv.sin_family = AF_INET;
// 设置端口 ,把主机字节转换成 络字节,根据查询1024以上随便写,最大是 65535
addrSrv.sin_port = htons(6000);
/*
*需要使用bind函数,将服务器Socket和服务器包进行绑定
*/
// 强制转换的作用在于:SOCKADDR_IN 地址包的形式,只是方便了我们设置参数
// 而使用的时候,bind还是需要把这些参数揉和到一起。
//在上面我们创建的socket名字是sockSer所以这里填socket应该是sockSer
bind(sockSer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
// 让服务器Socket开启监听,并且设置最大的等待连接数
// 等待连接数(半连接)过大会给服务器造成负载
(sockSer, 5);
//开启监听线程
LPVOID *lp = (LPVOID*)&sockSer;
HANDLE hThread = CreateThread(NULL, 0, ServerListeningConnect, lp, 0, NULL);
// SOCKADDR_IN addrClient;
// int len = sizeof(SOCKADDR);
int cnt = 0;
const int max_connet_cnt = 20;
(true) {
cnt++;
if (cnt > max_connet_cnt){
printf(“超出最大尝试连接次数,进程即将结束”);
system(“pause”);
//关闭socket库
closesocket(sockSer);
closesocket(sockCli);
WSACleanup(); //清空加载项
return 0;
}
cout
//连接接听请求
(sockSer, 5);
//接听连接请求
sockCli = accept(sockSer, (SOCKADDR*)&addrCli, &naddr);
if (sockCli != INVALID_SOCKET){
//连接成功
cout
strcpy(sendbuf, “hello!”);
send(sockCli, sendbuf, sizeof(sendbuf), 0);
// 接收操作
recv(sockCli, recvbuf, 50, 0);
printf(“%sn”, recvbuf);
break;
}
}
//全双工接听
(true)
{
char recvbuf[MAX_BUF_SIZE];
for (int i = 1; i
{
if (recv(Cli[i].s, recvbuf, sizeof(recvbuf), 0) != INVALID_SOCKET)
{
// 向另外的客户端进行发送
char sendbuf[SEND_SIZE];
strcpy(sendbuf, “[“);
strcat(sendbuf, Cli[i].name);
strcat(sendbuf, “]:>”);
strcat(sendbuf, recvbuf);
for (int j = 1; j
{
if (j == i)
continue;
printf(“服务器接收到了来自%d 发给 %d 的 %sn”, i, j, recvbuf);
printf(“服务器即将发送 %sn”, sendbuf);
send(Cli[j].s, sendbuf, SEND_SIZE, 0);
}
}
}
}
//关闭socket库
closesocket(sockSer);
closesocket(sockCli);
WSACleanup(); //清空加载项
}
文章知识点与官方知识档案匹配,可进一步学习相关知识 络技能树认识身边的计算机 络常见的 络设备22183 人正在系统学习中 相关资源:国内领先的在线试衣间软件3D试衣间_github3D试衣间源码-互联 …
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!