科技系列 - 2 < 更新第二期 >:DEV - C++ 不同主机下的同局域网联机 更新 第 2 期


DEV - C++ 不同主机下的联机 更新 第 Ⅱ 期

首期文章链接


上上期补充说明

相信很多人都发现上一期的程序无法 编译运行 (原因未知) ,我们只需要给程序的 编译命令( DEV-C++ 编译器 → 工具 → 编译选项 → 编译命令) 加上 -lws2_32 且把 #pragma 语句去掉就行了!!!


本期更新说明

本期更新将原有风格全部改变

新加:

1、可支持多人联机模式(运用多线程知识)

2、改换成由 客户端 -> 服务端 -> 客户端 的方法多人通话

3、可以设置服务器密码

注意:所有警告均为英语!

以下全文纯手打,给个 赞 行吗


版本 - 3

服务端
#include<bits/stdc++.h> 

#include<Winsock2.h>

#include<windows.h>

#include<queue>

#pragma comment (lib,"ws2_32") 

//使用 Winsock2.h 时需要用 ws2_32.lib 文件 

//如果出现编译错误 xxx.cpp:(.text+xxx): undefined reference to `__imp_xxx'

//可在编译命令处 添加 -lws2_32 

#define size 6400 // 缓冲区长度 

#define port 9999 // 端口号 

#define people 5 //限制人数 

using namespace std;

queue<char*> print; //发送信息缓冲

char names[10000][105]; //存储昵称 

SOCKET server; //接受 SOCKET 用 

SOCKET lient[100000]; //最多可承载次数 

int times_lient[100000]; //存储承载下标 ( 用来删除下线状态 ) 

int times; //承载过的次数 

int online; //在线人数 

char keys[1000];

bool p1_tf; //延时判断

bool p2_tf = true;

void get_keys()
{
	puts("Please set the room password! ( keys len < 50 )\n");
	
	gets(keys);
	
	puts("");
	
	if(strlen(keys) >= 50)
	
		printf("Oops! len = %d ( >= 50 )\n\n",strlen(keys)),
	
		get_keys();
}

DWORD WINAPI recvs(LPVOID param)
{
	SOCKET sclient = lient[times];
	
	p1_tf = false;
	
	int reg;
	
	char recvn[10000];
	
	memset( recvn , 0 , sizeof(recvn) );
	
	while(1)
	{
		memset( recvn , 0 , sizeof(recvn) );
		
		reg = recv(sclient , recvn , size , 0);
		
		if(reg == -1)
		
			break;
		
		else
		{
			printf("From %s : %s\n\n",names[sclient],recvn);
			
			char sssn[1000];
			
			memset(sssn,0,sizeof(sssn));
            
        	memcpy(sssn,names[sclient],strlen(names[sclient]));
        	
        	sssn[strlen(sssn)] = ':';
        	
            strcat(sssn,recvn);
            
            strcat(sssn,"\n");
            
            print.push(sssn);
		}
	}
	
	strcat(names[sclient]," left!\n");
    
    printf("%s\n\n",names[sclient]);
    
    lient[ times_lient[sclient] ] = -1;
    
    print.push(names[sclient]);
    
    online -- ;

    closesocket(sclient);
}

DWORD WINAPI sends(LPVOID param)
{
    while(1)

    	if(!print.empty() and p2_tf)
    	{
    		int ans = 0;
    		
    		for(int i = 1;i <= times;i ++)
    		
    			if(lient[i] != -1) 

    				send( lient[i] , print.front() , strlen(print.front()) , 0 ) ,
					
					ans++;
    				
    			else if(ans == online)
    			
    				break;

			print.pop(); 
		}

}

void find_socket()
{
	get_keys();
	
	sockaddr_in client;
	
    int client_len = sizeof( client );
	
	CreateThread(NULL, 0, sends , NULL, 0 , NULL);
	
	puts("Socket is open!\n");
	
	while(1)
	{
		if(times > 99999)
		{
			puts("Error 5 - Upper limit reached!\n ");
			
			puts("The server cannot be turned on normally!\n");
		
			puts("Close in five seconds!\n");
		
			Sleep(5000);
		
			exit(0);
		}
		
		if(online >= people)
		{
			printf("Error 6 - The number of people online has reached the maximum! ( %d People ) : ( Now %d people) \n\n ",people,online);
		
			puts("Please wait!\n");
		
			while(online >= people);
		}
		
		while(p1_tf);
		
		lient[++times] = accept( server, ( sockaddr FAR* )&client, &client_len );
		
		p2_tf = false;
		
		if( lient[times] == (SOCKET)(~0) )
		{
			puts("Error 7 - Access failure!\n ");
			
			times--;
			
			continue;
		}
		
		times_lient[lient[times]] = times;
		
		char phj[1000];
		
		memset(phj,0,sizeof(phj));
		
		int ret = recv( lient[times] , phj , size , 0);
		
		char keyss[1000];
		
		memset(keyss,0,sizeof(keyss));
		
		int yi = 0 , pi = 0;
		
		while(phj[pi] != ',')
		{
			names[lient[times]][pi] = phj[pi];
			
			pi++;
		}
		
		pi++;
		
		while(phj[pi] != ',')
		{
			keyss[yi ++] = phj[pi];
			 
			pi++;
		}

		if( strcmp( keys , keyss ) != 0 )
		{
			int reg = send( lient[times] , "-1" , strlen( "-1") , 0);
			
			printf("From [%s] , name [%s] password error!\n\n",reg,inet_ntoa(client.sin_addr),names[lient[times]]);
			
			Sleep(1000);
			
			times -- ;
			
			continue;
		}
		
		online ++;
		
		send( lient[times] , "-n-" , strlen( "--") , 0);
		
		printf("From [%s] , name :[%s] join successfully!\n\n",inet_ntoa(client.sin_addr),names[lient[times]]);
		
		char sssn[1000];
		
		memset(sssn,0,sizeof(sssn));
		 
    	memcpy(sssn,names[lient[times]],strlen(names[lient[times]]));
    	
    	strcat(sssn," 加入了服务器\n");
//    	
		print.push(sssn);
		
		p1_tf = p2_tf = 1;
		
		CreateThread(NULL, 0, recvs , NULL, 0 , NULL);
	}
}

void open_socket()
{
	/*
	This is an important part of communication.
	*/
	
	WSADATA wsaData;
	
	if( WSAStartup( MAKEWORD( 2 , 2 ) , &wsaData ) != 0)
	{
		puts("Error 1 - Winsock Load Error!\n");
		
		puts("The server cannot be turned on normally!\n");
		
		puts("Close in five seconds!\n");
		
		Sleep(5000);
		
		exit(0);
	}
	
	server = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP );
	            
	if( server == (SOCKET)(~0) )
	{
		puts("Error 2 - Socket Error!\n");
		
		puts("The server cannot be turned on normally!\n");
		
		puts("Close in five seconds!\n");
		
		Sleep(5000);
		
		WSACleanup();
		
		exit(0);
	}
	
	sockaddr_in bindser;
	
	bindser.sin_family = AF_INET; 
	
	bindser.sin_port = htons( port ); //指向端口号 
	
	bindser.sin_addr.s_addr = htonl( INADDR_ANY ); //指向全部人可连接
	
	if( bind( server , ( const struct sockaddr* ) &bindser , sizeof( bindser ) ) == (SOCKET)(~0) )
	{
		puts("Error 3 - Bind Error!\n");
		
		puts("The server cannot be turned on normally!\n");
		
		puts("Close in five seconds!\n");
		
		Sleep(5000);
		
        WSACleanup();
        
        closesocket( server );
		
		exit(0);
	}
	
	if( listen( server , people ) == (SOCKET)(~0) )
	{
		puts("Error 4 - Listen Error!\n");
		
		puts("The server cannot be turned on normally!\n");
		
		puts("Close in five seconds!\n");
		
		Sleep(5000);
		
        WSACleanup();
        
        closesocket( server );
		
		exit(0);
	}
}

int main()
{
	puts("Welcome to English LAN communicator!\n");
	
	open_socket(); // 开启 
	
	find_socket(); // 寻找 
} 
客户端
#include<bits/stdc++.h> 

#include<Winsock2.h>

#include<windows.h>

#include<queue>

#pragma comment (lib,"ws2_32") 

#define port 9999 

#define size 6400 // 缓冲区长度 

//使用 Winsock2.h 时需要用 ws2_32.lib 文件 

//如果出现编译错误 xxx.cpp:(.text+xxx): undefined reference to `__imp_xxx'

//可在编译命令处 添加 -lws2_32 

SOCKET server;

char your_name[1000];

char ipv4[1000];

char keys[1000];

void recvs()
{
	int rag;
	
	char recvn[100000];
	
	memset(recvn,0,sizeof(recvn));
	
	while(1)
	{
		memset( recvn , 0 , sizeof(recvn) );
		
		rag = recv(server,recvn,size,0);
		
		if(rag == -1)
		{
			puts("Error 5 - Disconnect the server!\n");
			
			break;
		}
		
		printf("%s\n",recvn);
	}
}

DWORD WINAPI sends(LPVOID param)
{
	char sendn[100000];
	
	memset( sendn , 0 , sizeof(sendn) );
	
	while(1)
	{
		puts("Send len < 1000\n");
		
		memset( sendn , 0 , sizeof(sendn) );
		
		gets(sendn);
		
		puts("");
		
		if(strlen(sendn) >= 1000)
		{
			printf("Oops! len = %d ( >= 1000 )\n\n",strlen(keys));
			
			continue;
		}
		
		int rag = send(server,sendn,strlen(sendn),0);
		
		if(rag == -1) break;
	}
}

void open_socket()
{
	WSADATA wsaData;
	
	if( WSAStartup( MAKEWORD( 2 , 2 ) , &wsaData ) != 0) 
	{
		puts("Error 1 - Winsock Load Error!\n");
		
		puts("The server cannot be turned on normally!\n");
		
		puts("Close in five seconds!\n");
		
		Sleep(5000);
		
		exit(0);
	}
	
	server = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP );
	            
	if( server == (SOCKET)(~0) )
	{
		puts("Error 2 - Socket Error!\n");
		
		puts("The server cannot be turned on normally!\n");
		
		puts("Close in five seconds!\n");
		
		Sleep(5000);
		
		WSACleanup();
		
		exit(0);
	}

	set_name:

	puts("Please set your name! ( name len < 20 )\n");
	
	gets(your_name);
	
	puts("");
	
	if(strlen(your_name) >= 20)
	{ 
	
		printf("Oops! len = %d ( >= 20 )\n\n",strlen(your_name)); 
		
		goto set_name;
		
	} 
	
	set_ipv4:

	puts("Please set ipv4\n");
	
	gets(ipv4);
	
	puts("");
	
	sockaddr_in conser;
	
	conser.sin_family = AF_INET; 
	
	conser.sin_port = htons( port ); //指向端口号 
	
	conser.sin_addr.S_un.S_addr = inet_addr(ipv4);
	
	set_keys:

	puts("Please set key\n");
	
	gets(keys);
	
	puts("");
	
	for(int i = 1;i <= 10;i++)
	{
		if(connect( server, (LPSOCKADDR)&conser, sizeof( conser ) ) == (SOCKET)(~0) )
		{
			if(i == 10)
			{
				puts("Error 3 - IP Error!\n");
		
				goto set_ipv4;
		
				exit(0);
			}
		}
		else
		{
			break;
		}
	}
	
	strcat(your_name,",");
	
	strcat(your_name,keys);
	
	strcat(your_name,",");
	
	send(server,your_name,strlen(your_name),0);
	
	char yes[100];
	
	memset(yes,0,sizeof(yes));
	
	int reg = recv(server,yes,size,0);
	
	if(strcmp(yes,"-n-") == 0)
	{
		puts("Error 4 - Key Errer!\n");
		
		Sleep(5000);
		
		return;
		
	}
	
	HANDLE hThread1 = CreateThread(NULL, 0, sends, NULL, 0, NULL);

	recvs();
	
    ::CloseHandle(hThread1);
         
    closesocket( server );
    
    WSACleanup(); // 资源释放

}

int main()
{
	again:
	
	open_socket();
	
	goto again;
}

使用说明

同局域网下方可链接


以后我会持续更新关于 DEV-C++ 联机的程序,以帮助大家利用联网制作更多有用的东西 “勿整蛊!!”

关于DEV-C++的黑科技系列,以后会持续更新,大家可以收藏作为资料使用!


  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: 上海海同信息科技是一家专注于网络安全培训的公司,其系列教程视频是该公司针对广大网络安全爱好者提供的一种学习资源。这些教程视频涵盖了许多网络安全的相关内容,如Web安全,网络渗透,恶意代码分析等等。通过这些视频,用户可以深入了解网络安全领域的相关知识以及学习实战技能。 这些教程视频可以通过网盘获取,一般来说,用户可以通过购买会员或者下载专区来获得视频资源。这些视频资源都是经过公司精心筛选和优化的,因此品质有保证。此外,这些视频还配有详细的讲解和演示,便于用户理解和掌握。对于初学者而言,这些教程视频也是一种非常好的入门方式,可以帮助他们更好地了解网络安全领域的基础知识和常用技能。 总之,上海海同信息科技系列教程视频网盘为广大网络安全爱好者提供了一种高质量、实用性强的学习资源,可以帮助他们更好地掌握网络安全领域的相关知识和技能,进而提升自身能力和竞争力。 ### 回答2: 上海海同信息科技c系列教程视频网盘是一项非常优质的在线教育服务。该网盘提供了一系列的C语言教程视频,通过实际案例和演示,帮助学习者加深对C语言语法和编程技巧的理解。 该网盘的教程视频由专业的讲师录制,对C语言的基础知识和高级应用进行了全面细致的讲解,每个视频都具有一定的难度和深度,非常适合不同层次的学习者使用。 在使用上海海同信息科技c系列教程视频网盘时,学习者可以根据自己的学习需要和兴趣选择需要学习的视频,并在学习过程中随时进行反复观看和实践操作,以便更好地掌握C语言的编程技巧和方法。同时,该网盘还提供了配套的实验代码和实验指导,帮助学习者更好地进行实践操作和掌握知识点。 总之,上海海同信息科技c系列教程视频网盘是一项非常优秀的在线C语言教育服务,不仅能够帮助学习者深入理解C语言的编程思想和方法,还能够提供充足的实践机会和指导,让学习者更好地掌握C语言编程的技能。 ### 回答3: 海同信息科技是一家专门提供IT技术培训的公司,其推出的系列教程视频网盘是对想要入门或提升技术的人士非常有用的资源。该系列教程涵盖了IT行业中的很多技术领域,比如Web开发、数据库、系统运维等等。这些教程既有基础的入门课程,也有更进阶的内容。由于制作者的水平高超,教程的语言简明易懂,内容丰富,所以很受技术学习者的欢迎。 海同信息科技系列教程视频网盘提供了非常便利的在线观看和下载方式,学习者可以随时随地获取对自己有用的知识。此外,海同信息科技的课程还提供在线提问和答疑,这对于遇到困难需要寻求帮助的学员来说非常有帮助。除了课程内容,海同信息科技还提供了海量的IT技术学习资源,比如技术文档、开发工具等等,学员可以下载使用。 总之,海同信息科技系列教程视频网盘是IT技术爱好者和从事IT行业的人士不可错过的学习资源,它能够帮助学员快速入门、深入学习和提升技术水平。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值