在Windows下利用visual studio完后socket服务器的搭建(可连接多个客户端)

socket服务器其实网上有很多的代码,但是大部分是基于Linux的,或者是Windows下的c++语言完成的设计,而且大部分是一对一的连接。今天发表一个C语言完成的socket服务器,可以实现一对多,多个客户端可以用IP和发送的数据来区分不同。另外,我的多客户端不是选择进程和多线程的办法,但是对于有需要的,我会添加线程和进程的使用。

注意:这是vs2017的环境,但是对于Windows大部分的编译器来说,是没有问题的,如果不行,对于报错的信息进行修改就可以了。如果是Linux的系统下,需要改的稍微多一点,但是万变不离其宗,基本上就是头文件名,参数和函数名的修改,整体的结构是我实验了很多次的。

1.socket服务器的代码 (一对一)

#include"pch.h"

#include <stdio.h>
#include <winsock2.h>
//#include<iostream>
//#define MaxSize 10000

#pragma comment(lib,"ws2_32.lib")

#define _WINSOCK_DEPRECATED_NO_WARNINGS//解决:inet_ntoa函数和无法使用inet_ntop的问题




int main(int argc, char* argv[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);//操作系统根据请求的Socket版本来搜索相应的Socket库,
									  //然后绑定找到的Socket库到该应用程序中。
									  //以后应用程序就可以调用所请求的Socket库中的其它Socket函数
	WSADATA wsaData;//WSADATA是一种数据结构,存储WSAStartup函数返回的数据
	if (WSAStartup(sockVersion, &wsaData) != 0)//第一个参数是版本号,第二个参数是保存start的返回值
	{
		return 0;
	}

	//创建套接字
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建面向网络的套接字,而且是有连接的,协议自然为TCP协议
	if (slisten == INVALID_SOCKET)//判断套接字是否创建成功
	{
		printf("socket error !");
		return 0;
	}

	//绑定IP和端口
	sockaddr_in sin;//处理网络通信地址的结构体,声明变量
	sin.sin_family = AF_INET;// TCP/IP协议族
	sin.sin_port = htons(80);//端口可以自己赋值
	sin.sin_addr.S_un.S_addr = INADDR_ANY;//设置的是服务器的IP地址,inet_addr("0.0.0.0"); 本地的IP地址是
										   //服务器端计算机上的所有网卡的IP地址都可以作为服务器IP地址
	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)//绑定并进行判断,套接字指向sockaddr_in结构体的指针,参数长度 
	{
		printf("bind error !");
	}

	for (int i=0; i<10;i++)
	{//开始监听
		if (listen(slisten, 10) == SOCKET_ERROR)//监听一个主动连接的套接字,一个队列内核上限(slisten 变为监听套接字)
		{
			printf("listen error !");
			return 0;
		}

		//循环接收数据
		SOCKET sClient;
		sockaddr_in remoteAddr;
		int nAddrlen = sizeof(remoteAddr);
		char revData[255];

		printf("等待连接...\n");
		sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);//返回值:连接套接字;参数:监听套接字,ADDR结构体,ADDR结构体的大小
		if (sClient == INVALID_SOCKET)//为空,继续
		{
			printf("accept error !");
			//continue;
		}
		printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
		while (true)
		{
			//接收数据
			int ret = recv(sClient, revData, 1024, 0);//指定套接字,接收的数据,buf,一般为0
			//printf("%s", &revData);
			if (ret > 0)
			{
				revData[ret] = 0x00;
				printf(revData);//显示接收的数据
				printf("\n");
			}

			//发送数据
			const char * sendData = revData;//对于客户端发送过来的数据,再原样反馈回去。

			send(sClient, sendData, strlen(sendData), 0);//参数说明:套接字,发送数据,长度,一般为0

			if (sClient == INVALID_SOCKET)//为空,继续
			{
				printf("listen error !");
				break;

			}
//			closesocket(sClient);
		}
		closesocket(sClient);
	}

	closesocket(slisten);//关闭
	WSACleanup();//清除
	return 0;

}

这是一对一连接成功的结果图,有问题的可以联系我。

代码编译的控制台                                      一个仿真软件做客户端,也可以自己写

2.进程的使用方法



		/*如果想使用多线程,可以在原有的基础上进行新的函数定义,然后用下面的办法创建,其中会有一些声明和变量的定义,可以通过编译器的报错来修改,基本上没有什么大问题了。当然,你要使用互斥锁可能难度更大一些*/
		HANDLE hThread01 = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)send, (LPVOID)sClient, 0, 0);//发送,send就是你所编辑的函数,可以替换,sclient就是你的创建的接收的数据套接字,也可修改
		if (hThread1 != NULL)
		{
			CloseHandle(hThread1);
		}
		HANDLE hThread02 = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)recv, (LPVOID)sClient, 0, 0);//接收,类比第一个线程
		if (hThread2 != NULL)
		{
			CloseHandle(hThread2);
		}
		Sleep(1000);	//must

3.一对多服务器,可以打开多个客户端连接

在一对一的基础上,可以使用线程的办法,实现一个服务器多个客户端,但是线程挺难的,所以说,我没有理解透彻,就换了一个办法,在Windows的环境下可以,在Linux的环境下,稍微修改一下头文件和函数名也可以实现。我这里给出Windows下一对多的服务器代码。

服务器的代码网址:https://download.csdn.net/download/jinfu5225/12342650

客户端是用的sscom仿真软件,这样的话,比较方便,有需要的下载:https://download.csdn.net/download/jinfu5225/12342561

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章