简单通讯聊天 群聊功能 Windows下的客户端 Linux下的epoll服务器
1 服务器代码 Linux eclipse C++
//============================================================================
// Name : epollServer.cpp
// Author : fangjunmin
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================ #include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/epoll.h>
#include <map>
#include <vector>
#include <memory.h>
#include "encode.h"
#include <stddef.h> using namespace std; int g_epfd = -;
int g_listen_fd = -;
u_short g_listen_port = ; typedef map<int, int> mapClient ;
typedef map<int, int>::iterator itmapClient ;
typedef map<int, int>::const_iterator citmapClient ; typedef vector<int> vecClient ;
typedef vecClient::iterator itvecClient ;
typedef vecClient::const_iterator citvecClient ; mapClient g_mapClient;
vecClient g_vecCLient; void InitListen();
void StartEpoll();
void BoardCast(const char* msg, long int nLen);
void removeFd(int fd); int main()
{
cout << "!!!Hello epoll!!!" << endl; // prints !!!Hello epoll!!! InitListen();
StartEpoll();
return ;
} void InitListen()
{
g_listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (g_listen_fd == -)
{
return ;
} struct sockaddr_in sin;
//bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(g_listen_port); if (bind(g_listen_fd, (struct sockaddr *) &sin, sizeof(struct sockaddr)) != )
{
printf("bind error: %d\n", errno);
return ;
} if (listen(g_listen_fd, ) != )
{
printf("listen error!\n");
return ;
}
} void StartEpoll()
{
int nSize = ;
g_epfd = epoll_create(nSize); epoll_event ev;
ev.data.fd=g_listen_fd;
ev.events = EPOLLIN | EPOLLET | EPOLLOUT;
int nAddResult = epoll_ctl(g_epfd ,EPOLL_CTL_ADD, g_listen_fd ,&ev); //将新的fd添加到epoll的监听队列中
if (nAddResult == -)
{
printf ("epoll_ctl error\n");
return ;
} while(true)
{
epoll_event events[nSize + ];
int nfds = epoll_wait(g_epfd, events, ,);
for(int i=; i<nfds; ++i)
{
printf("event num is: %d\n", nfds);
if(events[i].data.fd == g_listen_fd) //有新的连接
{
sockaddr_in clientaddr;
unsigned int clilen = sizeof(clientaddr);
int connfd = accept(g_listen_fd, (sockaddr *)&clientaddr, &clilen); //accept这个连接
printf("new connection! %d\n", connfd); epoll_event event;
event.data.fd=connfd;
event.events = EPOLLIN | EPOLLET | EPOLLOUT | EPOLLHUP;
epoll_ctl(g_epfd,EPOLL_CTL_ADD,connfd,&event); //将新的fd添加到epoll的监听队列中 g_vecCLient.push_back(connfd);
} else if( events[i].events & EPOLLIN ) //接收到数据,读socket
{
char szBuf[] = {};
int nRecvNum = recv(events[i].data.fd, szBuf, , ); //读 char szDest[] = {};
size_t nOutLen = ;
GB2312ToUtf8(szBuf, nRecvNum, szDest, nOutLen);
printf("recv size :%d, concent:%s\n", nRecvNum, szBuf);
printf("after conv size :%d, concent:%s\n", nOutLen , szDest); if(nRecvNum > )
{
BoardCast(szBuf, nRecvNum);
}
else if(nRecvNum == -)
{
perror(NULL);
removeFd(events[i].data.fd);
} // ev.data.ptr = md; //md为自定义类型,添加数据
// ev.events=EPOLLOUT|EPOLLET;
// epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改标识符,等待下一个循环时发送数据,异步处理的精髓
}
else if(events[i].events & EPOLLOUT) //有数据待发送,写socket
{
printf("EPOLLOUT\n" );
// struct myepoll_data* md = (myepoll_data*)events[i].data.ptr; //取数据
// sockfd = md->fd;
// send( sockfd, md->ptr, strlen((char*)md->ptr), 0 ); //发送数据
// ev.data.fd=sockfd;
// ev.events=EPOLLIN|EPOLLET;
// epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改标识符,等待下一个循环时接收数据
}
else if(events[i].events & EPOLLHUP) //socket disconnect
{
printf("socket disconnect socketid:%d\n", events[i].data.fd);
removeFd(events[i].data.fd);
}
else
{
//其他的处理
}
}
}
} void BoardCast(const char* msg, long int nLen)
{
for(citvecClient cit = g_vecCLient.begin(); cit != g_vecCLient.end(); cit++)
{
int nClientFd = *cit;
int nSendLen = send(nClientFd, (const void* )msg , nLen, );
printf("socket nSendLen:%d\n", nSendLen);
} } void removeFd(int fd)
{
epoll_ctl(g_epfd,EPOLL_CTL_DEL,fd, NULL); //delete socket in epoll
for(itvecClient it = g_vecCLient.begin(); it != g_vecCLient.end(); it++)
{
if(fd == *it)
{
g_vecCLient.erase(it);
return;
}
}
}
2 Windows下的客户端代码 Windows、visual studio 、C++
主线程 读线程 写线程
#include "stdio.h"
#include <WinSock2.h>
#include "cInitSock.h"
#include <string>
#pragma comment(lib,"WS2_32") using namespace std;
//struct stMsg
//{
// int sCmdID;
// int sLen;
// int nValue;
// string strContent;
//
// stMsg()
// {
// sCmdID = 0;
// sLen = 0;
// nValue = 0;
// strContent = "";
// }
//}; char g_szIp[] = "192.168.10.32";
short g_port = ;
SOCKET g_sock; void ReadHandle();
void WriteHandle();
CRITICAL_SECTION g_cs; static int s_na = ; void main()
{
cInitSock initSock;
InitializeCriticalSection(&g_cs);
g_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in sockAddr;
memset(&sockAddr,,sizeof(sockAddr)); sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.S_un.S_addr = inet_addr(g_szIp);
sockAddr.sin_port = htons((u_short)g_port);
int nRestle = ;
nRestle= connect(g_sock, (sockaddr *)&sockAddr, sizeof(sockAddr) ); DWORD dErr = GetLastError();
if (nRestle != )
{
printf("连接服务器失败 \n");
return;
}
printf("connect success \n"); int nReadThreadID;
int nWriteThreadID;
CreateThread(, , (LPTHREAD_START_ROUTINE) ReadHandle, , , (LPDWORD)&nReadThreadID);
CreateThread(, , (LPTHREAD_START_ROUTINE) WriteHandle, , , (LPDWORD)&nWriteThreadID); printf("客户端开启成功\n");
while()
{
;
} } void ReadHandle()
{
char buf[] = "";
int buflen = ; while ()
{
memset(buf, , );
buflen = recv(g_sock, buf, , );
if ( buflen )
{
EnterCriticalSection((LPCRITICAL_SECTION)&g_cs);
printf("recv msg : %s,msgSiez:%d\n", buf, buflen);
LeaveCriticalSection((LPCRITICAL_SECTION)&g_cs);
}
}
} void WriteHandle()
{
char buf[] = "";
int buflen = ; while ()
{
gets_s(buf);
//printf("the gets buf is:%s:end\n", buf);
buflen = send(g_sock, (const char* )&buf, strlen(buf), );
if ( buflen > )
{
EnterCriticalSection((LPCRITICAL_SECTION)&g_cs);
printf("send msg : %s,msgSiez:%d\n", buf, buflen);
LeaveCriticalSection((LPCRITICAL_SECTION)&g_cs);
}
if (buflen == -)
{
EnterCriticalSection((LPCRITICAL_SECTION)&g_cs);
printf("send msg error: %s\n", buf);
LeaveCriticalSection((LPCRITICAL_SECTION)&g_cs);
}
}
}
简单通讯聊天 群聊功能 Windows下的客户端 Linux下的epoll服务器的更多相关文章
- Java-->实现群聊功能(C/S模式--TCP协议)
--> Java 对TCP协议的支持: --> java.net包中定义了两个类ServerSocket 和Socket ,分别用来实现双向连接的server 端和client 端. -- ...
- day04-1群聊功能
多用户即时通讯系统04 4.编码实现03 4.5功能实现-群聊功能实现 4.5.1思路分析 群聊的实现思路和私聊的实现非常类似. 不同的是:私聊时,服务端接收到消息后,只需要找出接收方的socket并 ...
- 基于ejabberd简单实现xmpp群聊离线消息
首先,xmpp服务器是基于ejabberd.离线消息模块是mod_interact,原地址地址:https://github.com/adamvduke/mod_interact: 修改后实现群聊离线 ...
- 解决Windows下文件在Linux下打开出现乱码的问题
目录 问题 原理 解决 总结 参考资料 问题 前几天生病了,Java一直在看代码但是没跟着打,于是决定偷一波小小的懒,直接把教材的代码从Windows通过共享文件夹放到了Linux里面.但是编译的时候 ...
- windows下plsql连接linux下的oracle数据库
windows下plsql连接linux下的oracle数据库 经过多方查找,终于找到解决办法,特此记录下来,共享之. PL/SQL Develorper:目前未发现可以在Linux系统中安装的版本. ...
- ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(四) 添加表情、群聊功能
休息了两天,还是决定把这个尾巴给收了.本篇是最后一篇,也算是草草收尾吧.今天要加上表情功能和群聊.基本上就差不多了,其他功能,读者可以自行扩展或者优化.至于我写的代码方面,自己也没去重构.好的,我们开 ...
- netty无缝切换rabbitmq、activemq、rocketmq实现聊天室单聊、群聊功能
netty的pipeline处理链上的handler:需要IdleStateHandler心跳检测channel是否有效,以及处理登录认证的UserAuthHandler和消息处理MessageHan ...
- Java网络编程Demo,使用TCP 实现简单群聊功能Groupchat,创建一个服务端,使多个客户端都能收到消息
效果图: 开启服务端 客户端一 客户端二 客户端三 实现代码: 客户端类 import java.io.IOException; import java.net.ServerSocket; impor ...
- Asp.net SignalR 应用并实现群聊功能 开源代码
ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...
随机推荐
- Java常用类库——观察者设计模式
观察者设计模式 现在很多的购房者都在关注着房子的价格变化,每当房子价格变化的时候,所有的购房者都可以观察得到.实际上以上的购房者都属于观察者,他们都关注着房子的价格. 如果要想实现观察者模式,则必须依 ...
- shell更改xml中的指定值
sed -i 's;<id>.*<\/id>;<id>新内容<\/id>;g' your.xml
- Istio 1.4 部署指南
原文链接:Istio 1.4 部署指南 Istio 一直处于快速迭代更新的过程中,它的部署方法也在不断更新,之前我在 1.0 版本中介绍的安装方法,对于最新的 1.4 版本已经不适用了.以后主流的部署 ...
- 使用IDEA搭建一个 Spring + Spring MVC + Mybatis 的Web项目 ( 零配置文件 )
前言: 除了mybatis 不是零配置,有些还是有xml的配置文件在里面的. 注解是Spring的一个构建的一个重要手段,减少写配置文件,下面解释一下一些要用到的注解: @Configuration ...
- 安装nodejs与使用
nodejs 官方下载地址:https://nodejs.org/en/ 下载完成后,双击打开安装程序 然后: 然后点击install,等待安装 安装完成后的目录如下: 检测是否真的安装成功.打开cm ...
- Acwing-119-袭击(分治)
链接: https://www.acwing.com/problem/content/121/ 题意: 在与联盟的战斗中屡战屡败后,帝国撤退到了最后一个据点. 依靠其强大的防御系统,帝国击退了联盟的六 ...
- centos 修改时区以及修正时间
1.查看系统当前的时区 [app@127-0-0-1 shine]$ timedatectl Local time: Wed 2019-10-23 17:56:17 CST Universal tim ...
- JDK、JRE和JVM的区别与相互之间的联系
工作这么久,好多时间都在研究一些并发.多线程.分布式.框架等这些东西,但是前几天突然被人问到jdk.jre.jvm的区别与联系,瞬间觉得一脸懵逼,感觉还是有必要重新整理一下一些比较基本的java知识了 ...
- Miller Rabin 算法简介
0.1 一些闲话 最近一次更新是在2019年11月12日.之前的文章有很多问题:当我把我的代码交到LOJ上,发现只有60多分.我调了一个晚上,尝试用{2, 3, 5, 7, 11, 13, 17, 1 ...
- mysql bit 和 tinyint 的区别及使用场景?
bit类型语法:bit[(M)] : 位字段类型.M表示每个值的位数,范围从1到64.如果M被忽略,默认为1. tinyint是数字类型,存储小数, 一般对应编辑语言里的小字典或枚举类型. 节省空间的 ...