计算机网络实现计算机间的,【计算机网络】大作业-实现两台pc间交流的聊天软件...

#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 <= clientCount; 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 << "呐呐呐,载入socket库失败!" << 'n';

system("pause");

return 0;

}

cout << "呐呐呐,初始化成功!" << 'n';

//创建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 << "呐呐呐,本地IP是" << ip << "该电脑已经开启!n";

// 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 << "正在尝试连接中,请稍等n";

//连接接听请求

(sockSer, 5);

//接听连接请求

sockCli = accept(sockSer, (SOCKADDR*)&addrCli, &naddr);

if (sockCli != INVALID_SOCKET){

//连接成功

cout << "连接成功" << 'n';

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 <= clientCount; 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 <= clientCount; 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(); //清空加载项

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值