//server
#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
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 地址 客户端地址和服务器地址
SOCKET NewConnection; //用于接受来自客户端的链接
int clientCount = 0;
int naddr = sizeof(SOCKADDR_IN);
int Ret;
char sendbuf[BUF_SIZE];
char inputbuf[BUF_SIZE];
char recvbuf[BUF_SIZE]; //该结构体的目的是允许多台PC机对服务器进行访问
//全局函数
using namespace std;
int main(){
//\ 第一步,加载socket函数,载入socket库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
//setColor(COLOR_ERROR);
cout << "呐呐呐,载入socket库失败!" << '\n';
system("pause");
return 0;
} //\ 第二步,创建一个监听套接字sockser, 创建socket(地址描述(AF_INET格式 - ipv4),指定socket类型(使用的是流式套接字即TCP协议), 指定协议
if ((sockSer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){
printf("当前为无效套接,程序结束");
system("pause");
return 0;
}
//\ 第三步,初始化服务器的地址包,填写相关信息
/*
*1.AF_INET优先赋值,这是由于该值是告诉winsock我们使用的是ip地址簇
*2.填写用来通讯的ip地址
*3.填写端口号
*
*/
char ip[] = "192.168.81.90";
cout << "呐呐呐,本地IP是" << ip << "该电脑已经开启!\n";
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(5000);
addrSer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //\ 第四步,将创建的sockser套接字和上面填写的相关地址信息绑定在一起,bind函数有很多,我们要选择的是sock中的所以加头文件的时候要注意不要多加
if (bind((SOCKET)sockSer, (SOCKADDR *)&addrSer, sizeof(addrSer)) == SOCKET_ERROR)
{
printf("BIND_ERROR: %d\n", SOCKET_ERROR);
return 0;
} cout << "二次元世界连接成功!" << endl; //\ 第五步,让服务器Socket开启监听,并且设置最大的等待连接数,等待连接数(半连接)过大会给服务器造成负载 if (listen(sockSer, 5) == SOCKET_ERROR){
printf("LISTEN_ERROR: %d\n", SOCKET_ERROR);
system("pause");
return 0;
} //\ 第六步,客户端连接到达时,本服务器需接受连接,注意接受链接用的是客户端的变量即Cli int ClientAddrLen = sizeof(addrCli);
printf("正在接受连接...");
if ((NewConnection = accept(sockSer, (SOCKADDR *)&addrCli, &ClientAddrLen)) == INVALID_SOCKET)
{
printf("ACCPET_ERROR: %d\n", INVALID_SOCKET);
closesocket(sockSer);
return 0;
}
printf("检测到一个来自三次元的连接: %s 端口:%d\n", inet_ntoa(addrCli.sin_addr), ntohs(addrCli.sin_port)); //\ 第七步,开始接听,true情况下进程不关闭就不会结束,但需要考虑电脑
while (true)
{
//接收数据
Ret = recv(NewConnection, recvbuf, BUF_SIZE, 0);
if (Ret > 0) printf("JOJO对你说: %s\n", recvbuf);
else if (Ret < 0) printf("RECV_ERROR: %d\n", SOCKET_ERROR);
else
{ printf("对方觉得二次元浓度过高,退出了聊天!"); break;
} //发送数据
printf("\n说:");
scanf("%s", sendbuf);
if (strcmp(sendbuf, "quit") == 0) //退出 break;
if (send(NewConnection, sendbuf, BUF_SIZE, 0) == SOCKET_ERROR)
{ printf("消息发送失败!\n"); break;
}
}
//关闭连接
shutdown(NewConnection, SD_BOTH);
closesocket(NewConnection);
//关闭socket库
closesocket(sockSer);
//清空加载项
if (WSACleanup() == SOCKET_ERROR)
{
printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
return 0;
}
system("pause");
return 0;
}