Linux下C++通过pthread和socket实现一个简单的多线程聊天室

后续可以在server中定义一个类来储存每一个用户的信息,包括名字,socket等。

server.cpp

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include <string.h>
#include<pthread.h>
#include<iostream>
#include<vector>

using namespace std;
#define LOCAL_IP "127.0.0.1"
#define LOCAL_PORT 1234

pthread_mutex_t mutex;      //Define a mutex
string lastmessage;         //string to save the last message
struct user{int sock;string name;}; //struct to diliver the parameters of clients
vector<int> socks;          //save the clients' socks
//
int start_up(const char* local_ip,int local_port)
{
	int sock = socket(AF_INET,SOCK_STREAM,0);//1.build socket
	if(sock < 0){
		perror("socket");
		exit(1);
	}
	struct sockaddr_in local;//2.bind the socket to IP and PORT
	local.sin_family = AF_INET;
	local.sin_port = htons(local_port);
	local.sin_addr.s_addr = inet_addr(local_ip);
	const int on=1;
	
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));//set bind options to avoid error
	if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)//3.bind socket
	{
		perror("bind");
		exit(2);
	}
	else{cout<<"Bind success."<<endl;}
	if(listen(sock,MAX) < 0)
	{
		perror("listen");
		exit(3);
	}
	else{cout<<"Listenning."<<endl;}
	return sock;
}
void * HandlerRequest(void *arg)
{
    pthread_mutex_lock(&mutex);//lock
    user* t=(user*)arg;
    int new_sock=t->sock;
    string idname=t->name;
    while(true){
        char recvBuf[4024] = {};
        int rRes=recv(new_sock, recvBuf, 4024, 0);
        if(rRes>0)
            cout<<idname<<":"<<recvBuf<<"\t( socketID: "<<new_sock<<" )\n";
        else{
            cout<<idname<<" is out."<<endl;
            break;
        }
        lastmessage=idname+": "+recvBuf;
        
        for(auto i:socks){//send last message to non-current socket
            if(i!=new_sock){
                send(i,(char*)lastmessage.c_str(),lastmessage.length(),0);
            }
        }
    }
    close(new_sock);
    pthread_mutex_unlock(&mutex);//unlock
	pthread_exit(NULL);
}
int main()
{
	int sock = start_up(LOCAL_IP,LOCAL_PORT);
	
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	while(true){
        pthread_mutex_init(&mutex, NULL);
        int new_sock = accept(sock,(struct sockaddr *)&client,&len);

        char recvBuf[4024] = {};
        if(new_sock>0){
            recv(new_sock, recvBuf, 4024, 0);
            cout<<endl<<recvBuf<<" is connected."<<"( socket: "<<new_sock<<" )"<<endl;
            cout<<"----------------------"<<endl;
            socks.push_back(new_sock);
            cout<<socks.size()<<" clients connected."<<endl;
        }
        else{cout<<"Failed to accept."<<endl;}
        user t;
        t.name=recvBuf;t.sock=new_sock;
        pthread_t id;
        pthread_create(&id,NULL,HandlerRequest,&t);
        pthread_mutex_destroy(&mutex);
	}
    close(sock);
	return 0;
}

client.cpp

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include <string.h>
#include<pthread.h>
#include<iostream>
#include <cstring>
#define MAX 10
using namespace std;

#define LOCAL_IP "127.0.0.1"
#define LOCAL_PORT 1234
struct user{int sock;string name;};

void* receive(void* arg){
    int *temp=((int*)arg);
    int sock=*temp;
    while(true){
        char recvBuf[1024] = {};
        int reLen = recv(sock, recvBuf, 1024, 0);
        cout<<endl<<recvBuf<<endl;
    }
    pthread_exit(NULL);
}

int main()
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(LOCAL_PORT);
    server.sin_addr.s_addr = inet_addr(LOCAL_IP);
    string name;
    cout<<"What is your name?";
    getline(cin,name);
    if(connect(sock,(struct sockaddr *)&server,sizeof(server)) < 0)
    {
        perror("connect");
        return 2;
    }
    write(sock,(char*)name.c_str(),name.length());

    void* temp=&sock;
    pthread_t th;
    pthread_create(&th,NULL,receive,temp);
    while(true){
        string s;
        getline(cin,s);
        write(sock,(char*)s.c_str(),s.length());
    }

    close(sock);
    return 0;
}

图中右上角为server
其余三个均为client
在这里插入图片描述

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值