Qt:Qt实现Winsock网络编程—TCP服务端和客户端通信(多线程) 你的名字 2022-04-18 00:38 1131阅读 1赞 # Qt实现Winsock网络编程—TCP服务端和客户端通信(多线程) # ## 前言 ## 感觉Winsock网络编程的api其实和Linux下网络编程的api非常像,其实和其他编程语言的网络编程都差不太多。博主用Qt实现的,当然不想用黑窗口呗,有界面可以看到,由于GUI编程的话 一般UI进程不能阻塞,肯定需要多线来实现,在等待用户连接的时候accept,和客户端通信 等待消息的时候recv这些都是阻塞的 都需要在后台进程中。博主使用的是Qt5.9.7 ## 界面效果 ## 先看下效果再说 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI5NTQyNjEx_size_16_color_FFFFFF_t_70] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI5NTQyNjEx_size_16_color_FFFFFF_t_70 1] ## Winsock面向连接的接口 ## > Winsock初始化和释放 > > WSAStartup、WSACleanup > > 服务端: > > socket() -> bind() -> listen() -> accept() -> send() / recv() -> closesocket() > > 客户端: > > socket() -> connect() -> send() / recv() -> closesocket() 这些函数都在msdn上有,这里就不过多的阐述 ## 代码展示 ## 服务端 将与客户度建立连接的 过程放到单独的线程中进行处理了,这个线程 做的事就是等待客户端连接,客户端连接后 单独再开一个线程专门与客户度进行通信,这样就不会导致界面无响应了。这里线程和线程间的通信是使用的Qt中的信号槽机制。 ### 处理客户端连接请求代码 ### void SocketThread::run() { sockaddr_in clientAddr; int size = sizeof(clientAddr); while(!isInterruptionRequested()){ //每次接受新客户端将之前的地址信息清0 memset(&clientAddr,0,sizeof(clientAddr)); //等待新客户端连接 阻塞函数,结束线程 使用requestInterruption打断线程并没有用,只能使用terminate 终止线程 SOCKET client = ::accept(mListen,(sockaddr*)&clientAddr,&size); char* clientIp = inet_ntoa(clientAddr.sin_addr); int clientPort = ntohs(clientAddr.sin_port); QTime time = QTime::currentTime(); QString str = time.toString("hh:mm:ss"); QString msg = QString("%1 [%2:%3] connect success").arg(str).arg(clientIp).arg(clientPort); //新客户端连接,通知 UI 更新界面 emit isMsg(msg); //开启新线程和客户端进行通信 MsgThread* msgThread = new MsgThread(client,clientAddr,parent); msgThread->start(); connect(msgThread,&MsgThread::isMsg,this,[=](QString msg){ //转发消息给 UI进程,UI进行界面更新 emit isMsg(msg); }); connect(this,&SocketThread::isClose,this,[=](){ msgThread->terminate(); msgThread->quit(); delete msgThread; }); } } ### 服务端和客户端通信的代码 ### void MsgThread::run(){ //inet_addr点分十进制转网络ip地址 ,inet_ntoa网络转点分十进制 char* clientIp = inet_ntoa(mAddr.sin_addr); int clientPort = ntohs(mAddr.sin_port); while(true){ memset(resp,0,1024); char buf[1024] = {0}; //阻塞等待 接受信息 int ret = recv(mClient,buf,1024,0); QTime time = QTime::currentTime(); QString str = time.toString("hh:mm:ss"); if(ret == 0){//连接断开 emit isMsg(QString("%1 [%2:%3] is closed!!!").arg(str).arg(clientIp).arg(clientPort)); break; } QString msg = QString("%1 [%2:%3]:%4").arg(str).arg(clientIp).arg(clientPort).arg(buf); //接受到消息,通知UI 界面更新 emit isMsg(msg); //给用户进行响应消息,小写变大写 strcpy(resp,QString(buf).toUpper().toUtf8().data()); qDebug() << "给客户端发送消息:" << resp; send(mClient,resp,strlen(resp)+1,0); } } ## 完整代码 ## 完整项目代码可以点[这里进行下载][Link 1],或者[github下载最新代码][github]。 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI5NTQyNjEx_size_16_color_FFFFFF_t_70]: /images/20220418/34da3cb8b7ee4b78af2b0b6f8334a251.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI5NTQyNjEx_size_16_color_FFFFFF_t_70 1]: /images/20220418/9c97340a17244841a964352d9725b2c4.png [Link 1]: https://download.csdn.net/download/qq_29542611/10768890 [github]: https://github.com/licongxing/WinIPC_Socket_Tcp.git
还没有评论,来说两句吧...