linux c++ 简易聊天室

来源:互联网 发布:美业邦软件的弊端 编辑:程序博客网 时间:2024/06/05 03:29

c++聊天室编程记录(Linux环境基于eclipse c++)

server类

server.h

#ifndef SERVER_SERVER_H_#define SERVER_SERVER_H_#include <iostream>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/types.h>#include <arpa/inet.h>#include <time.h>#include <list>#include <errno.h>#include <pthread.h>#include <sstream>using namespace std;void* handClient(void* arg);void* announce(void* arg);class Server {public:    Server(const int& port);    ~Server();public:    void run();    friend void* handClient(void*);private:    void forwardMsg(const char* msg, size_t length);private:    int port;    int serverSock;    list<int>* clientsP;};static pthread_mutex_t printLocker = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t clientsLocker = PTHREAD_MUTEX_INITIALIZER;struct ThdArg{    int sockClient;    sockaddr_in addr;    void* mainObj;};#endif /* SERVER_SERVER_H_ */

server.cpp

#include "Server.h"Server::Server(const int& port) {    this->port = port;    this->clientsP = new list<int>;}Server::~Server() {    delete clientsP;}void Server::run() {    sockaddr_in addr;    if ((serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) {        cout << "create socket error" << endl;        exit(-1);    }    int opt = SO_REUSEADDR;    setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = htonl(INADDR_ANY);    addr.sin_port = htons(port);    if (bind(serverSock, (sockaddr*) &addr, sizeof(addr)) < 0) {        cout << "bind error" << endl;        exit(-1);    }    if (listen(serverSock, 50) < 0) {        cout << "listen error" << endl;        exit(-1);    }    cout << "server now is running, wait client to connect" << endl;    unsigned int addrLen = sizeof(sockaddr_in);    pthread_attr_t attr;    pthread_t tid;    while (true) {        ThdArg* arg = new ThdArg;        arg->mainObj = this;        arg->sockClient = accept(serverSock, (sockaddr*) &(arg->addr),                &addrLen);        pthread_attr_init(&attr);        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);        if (pthread_create(&tid, &attr, handClient, arg) < 0) {            cout << "create thread error" << endl;        }        pthread_attr_destroy(&attr);    }}void* handClient(void* arg) {    ThdArg* para = (ThdArg*) arg;    int clientSock = para->sockClient;    sockaddr_in addr = para->addr;    Server* serverP = (Server*) (para->mainObj);    ostringstream portStr;    portStr << addr.sin_port;    pthread_mutex_lock(&clientsLocker);    serverP->clientsP->push_back(clientSock);    pthread_mutex_unlock(&clientsLocker);    string hello(inet_ntoa(addr.sin_addr));    hello += ":";    hello += portStr.str();    hello += " join room\n";    serverP->forwardMsg(&hello[0], hello.length());    pthread_mutex_lock(&printLocker);    cout << hello;    pthread_mutex_unlock(&printLocker);    int ret;    fd_set set;    timeval tv = { 1, 0 };    char recvBuff[1024];    string msg;    while (true) {        FD_ZERO(&set);        FD_SET(clientSock, &set);        ret = select(clientSock + 1, &set, NULL, NULL, &tv);        if (ret <= 0) {            continue;        } else if (FD_ISSET(clientSock, &set)) {            ret = recv(clientSock, recvBuff, sizeof(recvBuff), 0);            if (ret <= 0) {                if (errno == EINTR)                    continue;                else                    break;            }            recvBuff[ret] = 0;            msg = inet_ntoa(addr.sin_addr);            msg += ":";            msg += (portStr.str()+":");            msg += recvBuff;            pthread_mutex_lock(&printLocker);            cout << recvBuff << endl;            pthread_mutex_unlock(&printLocker);            serverP->forwardMsg(&msg[0], msg.length());        }    }    string levMsg = (inet_ntoa(addr.sin_addr));    levMsg += ":";    levMsg += portStr.str();    levMsg += " disconnected\n";    serverP->forwardMsg(&levMsg[0], levMsg.length());    pthread_mutex_lock(&printLocker);    cout << levMsg;    pthread_mutex_unlock(&printLocker);    close(clientSock);    pthread_mutex_lock(&clientsLocker);    serverP->clientsP->remove(clientSock);    pthread_mutex_unlock(&clientsLocker);    delete para;    return 0;}void Server::forwardMsg(const char* msg, size_t length) {    char sendBuff[length];    strcpy(sendBuff, msg);    pthread_mutex_lock(&clientsLocker);    for(list<int>::iterator begin = clientsP->begin(); begin != clientsP->end(); ++begin){        if(send(*begin, sendBuff, length, 0) < 0){            pthread_mutex_lock(&printLocker);                cout << "one send error"<<endl;            pthread_mutex_unlock(&printLocker);        }    }    pthread_mutex_unlock(&clientsLocker);}

main.cpp

#include "server/Server.h"int main(){    Server server(6666);    server.run();    return 0;}

Client类

client.h

#ifndef CLIENT_CLIENT_H_#define CLIENT_CLIENT_H_#include <iostream>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/socket.h>#include <sys/types.h>#include <arpa/inet.h>#include <time.h>#include <errno.h>#include <pthread.h>using namespace std;void* recvMsg(void* arg);class Client {public:    Client(const char* serverIp, const int& port);    ~Client();public:    void run();    friend void* recvMsg(void* arg);private:    int sockClient;    char* serverIp;    int port;};#endif /* CLIENT_CLIENT_H_ */

client.cpp

#include "Client.h"Client::Client(const char* serverIp, const int& port) {    this->serverIp = (char*) serverIp;    this->port = port;}Client::~Client() {}void Client::run() {    sockaddr_in addr;    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr(serverIp);    addr.sin_port = htons(port);    sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);    if (connect(sockClient, (sockaddr*) &addr, sizeof(addr)) < 0) {        cout << "connect error" << endl;        exit(-1);    }    cout << "connect server success" << endl;    pthread_t tid;    pthread_attr_t attr;    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    int ret = pthread_create(&tid, &attr, recvMsg, this);    if (ret < 0) {        cout << "create thread error" << endl;    }    pthread_attr_destroy(&attr);    string msg;    while (true) {        cin >> msg;        send(sockClient, &msg[0], msg.length(), 0);    }    close(sockClient);}void* recvMsg(void* arg) {    Client* clientP = (Client*)arg;    int sock = clientP->sockClient;    char recvBuff[1024];    int ret;    fd_set set;    timeval tv = { 1, 0 };    while (true) {        FD_ZERO(&set);        FD_SET(sock, &set);        ret = select(sock + 1, &set, NULL, NULL, &tv);        if (ret <= 0){            continue;        }        else if (FD_ISSET(sock, &set)) {            ret = recv(sock, recvBuff, sizeof(recvBuff), 0);            if (ret <= 0) {                if (errno == EINTR){                    continue;                }                else{                    cout<<"you have been disconnected"<<endl;                    break;                }            }            recvBuff[ret] = 0;            cout << recvBuff << endl;        }    }    close(sock);    return 0;}

main.cpp

#include "client/Client.h"int main(){    Client client("127.0.0.1", 6666);    client.run();    return 0;}

运行

server
client
client
发送消息可能有些小bug

自学c++可能有许多漏洞或者不恰当的地方望见谅,以上需要配置多线程环境,eclipse->project->properties->c/c++ build->settings->gcc c++ linker ->libraries(-l)添加pthread库

原创粉丝点击