怎么用C++ SOCKET多线程实现聊天小程序(C++,socket,开发技术)

时间:2024-05-10 01:24:20 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

TCP/IP协议与SOCKET

什么是网络协议?

计算机网络中,各个实体之间的数据交换必须遵守事先约定好的规则,这些规则就称为协议。

网络协议的组成要素有:

1.语法,数据与控制信息的结构或格式
2.语义:需要发出何种控制信息,完成哪些动作以及做出何种响应
3.时序:事件实现顺序的详细说明

在一个网络协议中,通信的实体的相同层次的结构必须执行相同的协议,这是协议的对等性原则。

TCP/IP体系结构与SOCKET

怎么用C++ SOCKET多线程实现聊天小程序

关于TCP/IP体系结构的详细内容本文不做论述,如果你没有这方面的知识想要快速理解这个东西,可以把网络通信类比成两个人之间写信。你的信件就是通信过程中要传递的消息或者数据,而网络协议对你的“信件”进行了包装,比如给你贴了邮票、包了信封、投进了邮箱,然后你的“信件”就能通过邮局送到收信人那里。

SOCKET(套接字)是TCP/IP网络操作系统为网络程序开发提供的典型网络编程界面,进程通过SOCKET发送消息和接收消息。你可以把SOCKET看作一道“门”,发送消息的进程从“门”把消息推出去;消息被推出之后利用下层的通信设施传递到接收进程所在的“门”;然后接收进程再从“门”把消息拉进去。套接字SOCKET又分为数据报套接字和流式套接字,分别使用UDP协议和TCP协议。

SOCKET编程

我们尝试编写一个单播聊天室,这个聊天室可以让多个客户端与服务器端进行连接,而单播的意思是各个客户端只能与服务端进行单独通信,不同客户端之间无法通信。为了实现这个目标我们还需要用到多线程。整体实现思路如下图:

怎么用C++ SOCKET多线程实现聊天小程序

话不多说,上代码。

Server端

#include"stdafx.h"#include<WinSock2.h>#include<string.h>#include<iostream>#pragmacomment(lib,"ws2_32.lib")usingnamespacestd;constintPORT=8000;#defineIP"127.0.0.1"#defineMaxClient10//最多能接受同时在线的客户端数量,可以随意修改#defineMaxBufSize1024intnum=0;//客户端数量计数器#define_CRT_SECURE_NO_WARINGS//服务线程DWORDWINAPISeverThread(LPVOIDlpParameter){//新建一个SOCKET用于通信SOCKET*ClientSocket=(SOCKET*)lpParameter;intreceByt=0;charRecvBuf[MaxBufSize];charSendBuf[MaxBufSize];charexitBuf[5];//开始接收while(1){receByt=recv(*ClientSocket,RecvBuf,sizeof(RecvBuf),0);if(receByt>0){//当客户端发来的消息是“exit”,就关闭连接if(strlen(RecvBuf)==4){for(inti=0;i<5;i++){exitBuf[i]=RecvBuf[i];}intflag=strcmp(exitBuf,"exit");if(flag==0)//接收到exit消息{cout<<"client"<<*ClientSocket<<"exit!"<<endl;num--;send(*ClientSocket,"Yourserverhasbeenclosed",sizeof(SendBuf),0);closesocket(*ClientSocket);return0;}}cout<<"receivemessage:"<<RecvBuf<<"fromclient:"<<*ClientSocket<<endl;}else{//下面说到的客户端关闭连接是指客户端掉线了if(WSAGetLastError()==10054)//检测到客户端关闭连接{cout<<"client"<<*ClientSocket<<"exit!"<<endl;closesocket(*ClientSocket);num--;return0;}else//接收失败显示错误信息{cout<<"failedtoreceive,Error:"<<WSAGetLastError()<<endl;break;}}memset(RecvBuf,0,1024);cout<<"inputyourmessagetoclient:"<<endl;scanf_s("%s",SendBuf,MaxBufSize);intk=0;k=send(*ClientSocket,SendBuf,sizeof(SendBuf),0);if(k<0){if(WSAGetLastError()==10054)//检测到客户端主动关闭连接{cout<<"client"<<*ClientSocket<<"exit!"<<endl;closesocket(*ClientSocket);num--;return0;}else//发送失败显示错误信息cout<<"failedtosend,Error:"<<WSAGetLastError()<<endl;}memset(SendBuf,0,1024);}if(*ClientSocket!=INVALID_SOCKET){closesocket(*ClientSocket);}return0;}int_tmain(intargc,_TCHAR*argv[]){WSADatawsd;WSAStartup(MAKEWORD(2,2),&wsd);SOCKETListenSocket=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_INListenAddr;ListenAddr.sin_family=AF_INET;ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY;//本机ipListenAddr.sin_port=htons(PORT);//绑定监听端口intn;n=bind(ListenSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr));if(n==SOCKET_ERROR){cout<<"failedtobind!"<<endl;return-1;}else{cout<<"bindsuccessto:"<<PORT<<endl;}//开始监听intl=listen(ListenSocket,MaxClient);if(l==0){cout<<"serverready,waittorequirement..."<<endl;}else{cout<<"Error:"<<GetLastError()<<"listenreturn"<<l<<endl;}while(1){//循环接收客户端连接请求并创建服务线程if(num<MaxClient){SOCKET*ClientSocket=newSOCKET;HANDLEhThread;intSockAddrlen=sizeof(sockaddr);*ClientSocket=accept(ListenSocket,0,0);cout<<"client"<<*ClientSocket<<"hasconnecttoserver"<<endl;num++;hThread=CreateThread(NULL,NULL,&SeverThread,(LPVOID)ClientSocket,0,NULL);CloseHandle(hThread);}else{cout<<"MaxClient!Pleasewaitforaccept..."<<endl;}}closesocket(ListenSocket);WSACleanup();return0;}

在这个服务器端,每有一个新的客户端请求建立连接,服务器都会新开一个线程为一个客户端提供服务,并在这个线程中新建立一个SOCKET用于与客户端进行通信,同时服务器也应该能够在不同阶段(接收或发送)检测客户端是否已经断开连接,以便及时释放资源。

Client端

#include"stdafx.h"#include<iostream>#include<cstdio>#include<string>#include<Winsock2.h>#pragmacomment(lib,"ws2_32.lib")usingnamespacestd;constintPORT=8000;#defineMaxBufSize1024#define_CRT_SECURE_NO_WARINGSint_tmain(intargc,_TCHAR*argv[]){WSADATAwsd;WSAStartup(MAKEWORD(2,2),&wsd);SOCKETSocketClient=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_INClientAddr;ClientAddr.sin_family=AF_INET;ClientAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");ClientAddr.sin_port=htons(PORT);intn=0;n=connect(SocketClient,(structsockaddr*)&ClientAddr,sizeof(ClientAddr));if(n==SOCKET_ERROR){cout<<"failedtoconnect"<<endl;return-1;}cout<<"successtoconnecttoServer"<<endl;charinfo[1024];//数据输入缓冲区charSendBuff[MaxBufSize];//发送数据缓冲区charRecvBuff[MaxBufSize];//接收数据缓冲区while(1){cout<<"inputyourmessage:"<<endl;scanf_s("%s",&info,MaxBufSize);if(info[0]=='\0')break;strcpy(SendBuff,info);memset(info,0,sizeof(info));intk=0;k=send(SocketClient,SendBuff,sizeof(SendBuff),0);memset(SendBuff,0,sizeof(SendBuff));if(k<0){cout<<WSAGetLastError()<<endl;cout<<"failedtosend"<<endl;}intn=0;n=recv(SocketClient,RecvBuff,sizeof(RecvBuff),0);if(n>0){cout<<"receivemessagefromServer:"<<RecvBuff<<endl;memset(RecvBuff,0,sizeof(RecvBuff));}}closesocket(SocketClient);WSACleanup();return0;}

在本例中,客户端与服务器建立连接后,必须由客户端先发送消息才能开启对话。支持中英文聊天,一次最多发送1024个字节的数据。你要建立多个客户端的话只需要再新建几个工程然后把Client的代码复制进去运行即可。或者直接多复制几个编译生成的exe程序。

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:怎么用C++ SOCKET多线程实现聊天小程序的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:影响小程序服务器租用价格的因素有哪些下一篇:

14 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18