select加线程的服务端代码
来源:互联网 发布:大数据是以hadoop 编辑:程序博客网 时间:2024/06/07 18:09
服务端:
#include"stdafx.h"
#include <WinSock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
//存储所有的客户端套接字
fd_set g_fdClientSock;
//线程函数声明
DWORD WINAPI ThreadProc(LPVOID lpParameter);
int main()
{
// 初始化Winsock 2.2
WSAData wsaData;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
cout << "WSAStartup error:" << WSAGetLastError()<<endl;
return -1;
}
//创建监听套接字
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
cout << "socket() Error: " << WSAGetLastError() << endl;return 0;
}
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8000);
sin.sin_addr.S_un.S_addr = ADDR_ANY;
//绑定到本机任意地址
if (SOCKET_ERROR == bind(sListen, (sockaddr*)&sin, sizeof(sin)))
{
cout << "bind error:" << WSAGetLastError() << endl;
return -1;
}
//监听套接字
if (listen(sListen, 5) == SOCKET_ERROR)
{
cout << " listen() Error:" << WSAGetLastError() << endl;
return 0;
}
//创建一个线程,利用select即可处理多个客户端
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
CloseHandle(hThread);//关闭对线程的引用
//1)初始化一个套接字集合fdSocket,并将监听套接字放入
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(sListen, &readSet);
while (true)
{
//同时检查套接字的可读可写性。
int ret= select(0, &readSet, NULL, NULL, NULL);//若不设置超时则select为阻塞
if (ret >0) //-1
{
//是否存在客户端的连接请求。
if (FD_ISSET(sListen, &readSet))//在readset中会返回已经调用过listen的套接字。
{
//是否超过限制
if (g_fdClientSock.fd_count < FD_SETSIZE)
{
sockaddr_in addrRemote;
int nAddrLen = sizeof(sockaddr);
SOCKET sClient = accept(sListen, (sockaddr*)&addrRemote, &nAddrLen);
if (sClient != INVALID_SOCKET)
{
FD_SET(sClient, &g_fdClientSock);
cout << sClient << "进入聊天室!" << endl;
char tmp[64];
sprintf(tmp, "欢迎%d进入聊天室!", sClient);
send(sClient, tmp, strlen(tmp), 0);
}
}
}
}
else if (ret == 0)
{
cout<<"selct time out!"<<endl;
}
else
{
cout << "select error:" << WSAGetLastError() << endl;
}
Sleep(1000);
}
//关闭套接字
closesocket(sListen);
// 最后应该做一些清除工作
if (WSACleanup() == SOCKET_ERROR)
{
cout << "WSACleanup 出错!" << endl;
}
}
//线程中接收与发送消息
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
fd_set fdRead;
FD_ZERO(&fdRead);
char buf[64] ;
while (true)
{
//将客户端套接字集合赋值给fdRead
fdRead = g_fdClientSock;
int nRet = select(0, &fdRead, NULL, NULL, NULL);
if (nRet != SOCKET_ERROR)
{
//遍历集合,检查套接字是否还在
for (int i = 0; i < g_fdClientSock.fd_count; i++)
{
if (FD_ISSET(g_fdClientSock.fd_array[i], &fdRead))
{
SOCKET c = g_fdClientSock.fd_array[i];
memset(buf, 0, 64);
nRet = recv(c, buf, 64, 0);
if (nRet == SOCKET_ERROR)
{
closesocket(g_fdClientSock.fd_array[i]);
FD_CLR(c, &g_fdClientSock);
cout << c << "离开了!" << endl;
}
else
{
cout << c << "说: " << buf << endl;
}
}
}
}
}
return 0;
}
客户端
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std;
int main()
{
// WSADATA 结构体主要包含了系统所支持的Winsock版本信息
WSADATA wsaData;
// 初始化Winsock 2.2
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup 无法初始化!" << endl;
return 0;
}
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
cout << "socket() Error: " << WSAGetLastError() << endl;
return 0;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(8000);
if (connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
cout << "connect() Error: " << WSAGetLastError() << endl;
}
//接收服务端的信息
char buf[64];
memset(buf, 0, 64);
recv(s, buf, 64, 0);
cout << buf << endl;
int ret = 0;
do
{
char buf[64];
cout << "请输入聊天内容:" ;
cin >> buf ;
ret = send(s, buf , strlen( buf), 0);
} while (ret != SOCKET_ERROR && ret != 0);
closesocket(s);
// 最后应该做一些清除工作
if (WSACleanup() == SOCKET_ERROR)
{
cout << "WSACleanup 出错!" << endl;
}
return 0;
}
- select加线程的服务端代码
- select服务端代码实现
- 基于select的服务端
- epoll,select,poll单线程服务端示例
- select 非阻塞 sock服务端客户端代码实例
- java线程池加队列 代码例子
- exist后select加数字的理解
- 线程加解锁的问题
- 服务端的线程池方案1
- 服务端的线程池方案2
- winsock select服务端模型
- socket服务端的实现,select和epoll的区别
- 服务端并发问题以及epoll和select的区别
- 加资源的JASS代码
- 加双层边框的代码
- 详解多线程的两种实现方式以及4个线程,两个线程对j加1,两个线程对j减1完整代码。
- select 选中的js代码
- select模型的示例代码
- 聚类算法-dbscan算法的研究
- 深度学习(卷积神经网络)问题总结
- Node.js学习(1) 开发环境安装
- LeetCode
- 为什么每次开机第一次启动程序会很慢?
- select加线程的服务端代码
- bzoj1196[HNOI2006]公路修建问题
- Update an entity using spring data JPA
- 服务配置中心及负载均衡算法
- 逆序不重复的整数
- Android中有关数据库的知识总结
- ContentProvider和BroadcastReceiver
- eui时间范围控制,添加和修改
- Windows 64bit安装CodeWarrior V6.3