socket提供了套接字,以方便我们想读取文件一样进行网络进程间的数据通信。
在网络通信中,套接字一定是成对出现的。一端的发送缓冲区对应对端的接收缓冲区。我们使用同一个文件描述符索发送缓冲区和接收缓冲区。
服务器端的一对多代码实现:
(14条消息) 用C++实现简单的一对多Socket通讯(二)_two L的博客-CSDN博客_c++ socket 一对多
源码已经封装好了,比较好,是面向对象的。但是面向过程上不易读,我稍作修改。
#include <iostream> #include <WinSock2.h> #include <vector> #include <thread> #include <mutex> #pragma comment(lib,"ws2_32.lib") #pragma warning(disable:4996) typedef struct serverThread { std::thread *t1 = nullptr; bool isRuning = false; int threadID = -1; SOCKET csocket = -1; }Sthread; void ThreadClientRecv(Sthread *sthread) { while (sthread->isRuning == true) { // 从客户端接收数据 char buff[65535]; int nRecv = recv(sthread->csocket, buff, 65535, 0);//从客户端接受消息 if (nRecv > 0) { char str[50]; sprintf_s(str, "%dthread send message", sthread->threadID); char mess[] = "server:收到了你的消息。"; send(sthread->csocket, mess, sizeof(mess), 0); } else { char str[50]; sprintf_s(str, "ID%d is exit", sthread->threadID); sthread->isRuning = false; } } return; } int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) std::cout<<"Socket版本错误"; SOCKET m_nServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //设定TCP协议接口;失败返回INVALID_SOCKET if (m_nServerSocket == INVALID_SOCKET) { return 0; } int nRet = -1; if (m_nServerSocket != -1) { sockaddr_in Serveraddr; memset(&Serveraddr, 0, sizeof(sockaddr_in*)); Serveraddr.sin_family = AF_INET; Serveraddr.sin_addr.s_addr = inet_addr("192.168.1.107"); Serveraddr.sin_port = htons(1111); nRet = bind(m_nServerSocket, (sockaddr *)&Serveraddr, sizeof(Serveraddr)); //绑定服务器地址和端口号;成功,返回0,否则为SOCKET_ERROR } if (nRet == SOCKET_ERROR) { std::cout<<"绑定IP和端口失败"<<std::endl; return 0; } if (m_nServerSocket != -1) { nRet = listen(m_nServerSocket, 5);//设定接受连接的套接字,以及设定连接队列长度;成功返回0,失败返回-1 } if (nRet == SOCKET_ERROR) { std::cout << "监听绑定失败"<<std::endl; return false; } std::vector<Sthread*> m_Vecthread; static int m_CsocketCount = 0; while (m_nServerSocket != -1) { sockaddr_in nClientSocket;//如果要保存客户端的IP和端口号,就存在本地 int nSizeClient = sizeof(nClientSocket); SOCKET sClient = accept(m_nServerSocket, (sockaddr*)&nClientSocket, &nSizeClient);//接受客户端连接,阻塞状态;失败返回-1 if (sClient == SOCKET_ERROR) { std::cout<<"当前与客户端连接失败"<<std::endl; return 0; } else { Sthread *it = new Sthread(); it->threadID = ++m_CsocketCount; it->isRuning = true; it->csocket = sClient; std::thread t(ThreadClientRecv,it); t.detach(); it->t1 = &t; m_Vecthread.push_back(it); char str[50]; sprintf_s(str, "%dthread connect is success", it->threadID); char mess[] = "sercer:与服务器连接成功!"; send(sClient, mess, sizeof(mess), 0);//发送消息给客户端 } Sleep(25); } closesocket(m_nServerSocket); WSACleanup(); return true; }
我贴一张自己写的UDP的客户端
#include <WinSock2.h> #include <iostream> #pragma comment(lib,"ws2_32.lib") #pragma warning(disable:4996) int main() { WORD wVersion = MAKEWORD(2, 2); WSADATA wsadata; if (WSAStartup(wVersion, &wsadata) != 0) { return 0; } //反初始化操作 SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); //第一个参数协议簇(AF_INET,ipv4;AF_INET6,ipv6;AF_UNIX,本机通信) //第二个参数类型(SOCK_STREAM,TCP流;SOCK_DGRAM,UDP数据报;SOCK_RAW,原始套接字) //第三个参数一般设置0,当确定套接字使用的协议簇和类型时,这个参数的值就为0 if (s == INVALID_SOCKET) { return 0;//创建套接字失败 } sockaddr_in add; int len = sizeof(sockaddr_in); add.sin_family = AF_INET;//协议簇 add.sin_addr.S_un.S_addr = inet_addr("192.168.1.107");//主动连接该ip地址 add.sin_port = htons(11111);//网络字节序是大尾方式,本地字节序是小尾方式,需要转换 int i = connect(s, (sockaddr*)&add, len); if (SOCKET_ERROR == i) { return 0; } while (true) { char sbuf[256] = { 0 }; int ret = recv(s, sbuf, 256, 0); if (ret == 0) { break;//连接断开 } else if (ret > 0) { std::cout<<sbuf; } } closesocket(s); WSACleanup(); }
标签:socket,int,编程,C++,char,str,sthread,include,SOCKET From: https://www.cnblogs.com/xmds/p/16917814.html