Socket:多客户端与服务器通信

最近需要用到进程间通信模式处理消息,Socket是一种方便的网络进程通信工具,奈何作为初学者,无法领悟到里面的精髓。
通用的代码网上一搜一大堆:

//服务端(Server)
#include <stdio.h>
#include <iostream>

#include "conio.h"
#include "windows.h"
#include "winsock.h"
//socket库的lib
#pragma comment(lib,"ws2_32.lib")
void main()
{
    //初始化socket库
	WSADATA wsa = {0}; //WinSockApi 取WSA+DATA组成套接字结构体
	WSAStartup(MAKEWORD(2,2),&wsa);
	
	SOCKET socksvr;
	//SOCKET sockclient;
	/***************创建服务器端套接字SOCKET*******************/
	/*******socket()函数解释:IP协议族,数据流方式,TCP协议****/
	socksvr=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(INVALID_SOCKET == socksvr)
	{
		return;
	}
	/*************建立服务器端套接字地址***********************/
	/********************绑定IP和端口号******************/
	struct sockaddr_in svraddr = {0};
	svraddr.sin_family = AF_INET;//代表internet协议族
	svraddr.sin_port = htons(5678);
	svraddr.sin_addr.S_un.S_addr = inet_addr("172.16.20.111")/*htonl(INADDR_ANY)*/;//此宏为0,当前机器上任意IP地址,也可以指定当前机的ip和端口。
	//绑定,将服务器端套接字与服务器端套接字地址绑定
	bind(socksvr,(struct sockaddr *)&svraddr,sizeof(svraddr));//指定名字,类型,长度。绑定套接字。
	//侦听
	int state = listen(socksvr,SOMAXCONN);//第一个参数是套接字,第二个参数是等待连接队列的最大长度。
	//等候客户端建立连接 
	printf("等候客户端.......\n");
	//建立客户端套接字地址,主要是为了接收客户端返回参数之用
	struct sockaddr_in clientaddr = {0};
	int nLen = sizeof(clientaddr);

	while(true)
	{
	    SOCKET sockclient = accept(socksvr,(struct sockaddr*)&clientaddr,&nLen);//建立连接函数
		printf("客户端已连接\n");
		/********以下是数据收发部分*********/
		//先接收后发送,由上面知,数据已在sockclient中,我们只需读此结构便可知晓数据
		CHAR szText[100] = {0};
		//接收缓冲区数据 
		recv(sockclient,szText,nLen,0); //接收函数,一直处于侦听模式,等待服务器端发送数据的到来。
		printf("%s\n",szText);
		//关闭socket
		closesocket(sockclient);
	}
    //closesocket(sockclient);
	closesocket(socksvr);
	//清理套接字资源
	WSACleanup();
   //Client
   #include <stdio.h>
#include "conio.h"
#include "windows.h"
#include "winsock.h"
#pragma comment(lib,"ws2_32.lib")

void main()
{
    //初始化socket库
	WSADATA wsa = {0}; //WinSockApi 取WSA+DATA组成套接字结构体
	WSAStartup(MAKEWORD(2,2),&wsa);
	//创建socket
	SOCKET sockclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sockclient)
	{
		return;
	}
	//连接服务器,建立服务器端套接字地址
	struct sockaddr_in addr = { 0 };
	addr.sin_family = AF_INET;
	addr.sin_port = htons(5678);
	addr.sin_addr.S_un.S_addr = inet_addr("172.16.20.111");//本机ip

	//向服务器发出连接请求,当然我们也可以通过connet函数的返回值判断到底有无连接成功。
	int iRetVal = connect(sockclient, (struct sockaddr*)&addr, sizeof(addr));
	if (SOCKET_ERROR == iRetVal)
	{
		printf("服务器连接失败!");
		closesocket(sockclient);
		return;
	}
	printf("服务器连接成功!\n");
	//数据收发
	int num = 0;
	while(1)
	{
		CHAR szSend[100] = "hello server";   //客户端  先发后收
		int ret = send(sockclient, szSend, sizeof(szSend), 0);  //发送函数,可以通过返回值判断发送成功与否。
	}
	//  getch();//暂停一下
	//关闭socket
	closesocket(sockclient);
		//清理套接字资源
	WSACleanup();
}

上面的模式有个问题:只能单客户端通信、单次接收消息。
原因:服务端的accept()阻塞了。
解决策略:服务端建立两个线程,主线程用来监听客户端的接入,子线程实现服务器与客户端的通信。
参考了:https://blog.csdn.net/qq_37041925/article/details/83064164#commentBox

//Server
#include <stdio.h>
#include <iostream>

#include "conio.h"
#include "windows.h"
#include "winsock.h"
//socket库的lib
#pragma comment(lib,"ws2_32.lib")
#define MaxClient 10
#define MaxBufSize 1024
#define PORT 5678
DWORD WINAPI ServerThread(LPVOID lpParameter)
{
	SOCKET *ClientSocket=(SOCKET*)lpParameter;
	int receByt=0;
	char RecvBuf[MaxBufSize];
	while(1)
	{
		receByt = recv(*ClientSocket,RecvBuf,sizeof(RecvBuf),0);
		//buf[receByt]='\0';
		if(receByt>0){
			std::cout<<"接收到的消息是:"<<RecvBuf<<std::endl;
		}
 		else
 		{
			break;
    	}
       memset(RecvBuf,0,sizeof(RecvBuf));
	}
	closesocket(*ClientSocket);
	free(ClientSocket);
	return 0;
}
int main()
{
	WSAData wsd;
	WSAStartup(MAKEWORD(2,2),&wsd);
	SOCKET ListenSocket = socket(AF_INET,SOCK_STREAM,0);
	SOCKADDR_IN ListenAddr;
	ListenAddr.sin_family=AF_INET;
	ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY;//表示填入本机ip
	ListenAddr.sin_port=htons(PORT);
	int n;
	n=bind(ListenSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr));
	if(n==SOCKET_ERROR)
	{
		std::cout<<"端口绑定失败!"<<std::endl;
		return -1;
	}
	int l =listen(ListenSocket,SOMAXCONN);
	while(1)
	{
		//循环接收客户端连接请求并创建服务线程
		SOCKET *ClientSocket = new SOCKET;
		ClientSocket=(SOCKET*)malloc(sizeof(SOCKET));
		//接收客户端连接请求
		int SockAddrlen = sizeof(sockaddr);
		*ClientSocket = accept(ListenSocket,0,0);
		CreateThread(NULL,0,&ServerThread,ClientSocket,0,NULL);
	}
	closesocket(ListenSocket);
	WSACleanup();
	return(0);
}

于是实现了多客户端与服务端的通信!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mirinda_cjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值