实现简易的基于TCP/IP 协议的聊天室
项目描述:运用 socket 编程,实现了服务端对客户端的广播和转发客户端信息实现客户端聊天操作,并使用 i/o 复用技术中的 epoll 模式解决了一个线程可以处理大量用户连接服务器的请求,提高了服务器并发连接的数量。同时利用线程池来管理各个线程的工作,避免了创建和销毁线程的开销,因此使服务器更加高效。
server服务器:
// 一服务器 -> 多客户端
// 三次握手主要是创建连接
// 四次挥手主要是释放资源
// I/O复用 epoll模式
#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h> // bzero()
#include <pthread.h>
#include <list> // remove()
#include <thread>
#include <algorithm> // max_element()
#include <sys/epoll.h> // epoll()
#include <linux/fs.h> // OPEN_MAX
using namespace std;
void show_connect(int fd) {
// 获取本地地址和端口
struct sockaddr_in local_addr;
socklen_t local_addr_len = sizeof(local_addr);
bzero(&local_addr,local_addr_len); // 清空 防止后面误用
getsockname(fd,(struct sockaddr*)&local_addr,&local_addr_len);
cout << "local " << inet_ntoa(local_addr.sin_addr) << ":" << ntohs(local_addr.sin_port) << endl;
// 获取远程地址和端口
struct sockaddr_in remote_addr;
socklen_t remote_addr_len = sizeof(remote_addr);
bzero(&remote_addr,remote_addr_len);
getpeername(fd,(struct sockaddr*)&remote_addr,&remote_addr_len);
cout << "remote " << inet_ntoa(remote_addr.sin_addr) << ":" << ntohs(remote_addr.sin_port) << endl;
}
// ./server ip port
int main(int argc,char* argv[]) {
if(3!=argc) {
cout << "Usage:" << argv[0] << " IP port" << endl;
return 1;
}
// 1. 监听套接字
int listenfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listenfd) {
cout << "listen socket error" << endl;
return 1;
}
// 为了避免端口被占用,想要再次使用同一个端口
// 设置端口重复利用(一般用在调试中)
int flag = 1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag));
// 2. 绑定
struct sockaddr_in local_addr;
local_addr.sin_family = AF_INET; // IPv4协议
local_addr.sin_addr.s_addr