多线程聊天室

**

计算机网络——linux下多线程聊天室

**

客户端 client.c

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

int sockfd;

//获取当前时间
int GetTime(char *nowT) {
    time_t now;
    struct tm *pTM;

    time(&now);
    pTM = localtime(&now);

    sprintf(nowT, "%04d-%02d-%02d %02d:%02d:%02d\n  ",
            pTM->tm_year+1900, pTM->tm_mon+1, pTM->tm_mday,
            pTM->tm_hour, pTM->tm_min, pTM->tm_sec);
    return 0;
}

//接收服务器消息
void *TalkWithOther(void *arg)
{
    char buf[240];
    while(1)
    {
        bzero(buf,sizeof(buf));
        recv(sockfd,buf,sizeof(buf),0);
        printf("%s\n",buf);
    }
}

int main(int argc,char **argv)
{
    if(argc != 3)
    {
        perror("参数输入错误!");
        return -1;
    }

    //建立socket对象
    sockfd = socket(AF_INET,SOCK_STREAM,0);

    //准备连接地址
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;  //使用网络套接字
    addr.sin_addr.s_addr = inet_addr(argv[1]);  //输入服务器地址
    addr.sin_port = htons(atoi(argv[2]));       //输入服务器端口

    int addr_len = sizeof(addr);
    //连接服务器
    int ret = connect(sockfd,(struct sockaddr*)&addr,addr_len);
    if(ret == -1)
    {
        perror("connect error\n");
        return -1;
    }

    char buf[200] = {}; //聊天内容
    char buf_send[240] = {};    //加上当前时间的聊天内容
    char name[20] = {}; //昵称
    char *nowTime;

    //发送名字
    printf("请输入您的昵称:");
    scanf("%s",name);
    getchar();
    send(sockfd,name,strlen(name),0);
    //printf("%s已进入聊天室\n",name);

    //创建接收消息的线程
    pthread_t tid;
    pthread_create(&tid,NULL,TalkWithOther,NULL);

    //循环获取键盘输入并发送
    while(1)
    {
        fgets(buf,sizeof(buf),stdin);   //输入聊天内容
        buf[strlen(buf)-1]='\0';        //去除fgets读取到的最后的换行符

        //若输入quit,退出聊天室
        if(strcmp("quit",buf)==0)
        {
            send(sockfd,buf,strlen(buf),0);
            printf("%s,您已退出聊天室\n",name);
            return 0;
        }
        else{
            GetTime(nowTime);   //获取当前时间
            printf("%s\t%s%s\n",name,nowTime,buf);  //将消息在本地显示出来
            bzero(buf_send,sizeof(buf_send));      //清空发送字符串
            strcat(buf_send,nowTime);   //将当前时间写入字符串
            strcat(buf_send,buf);       //将聊天内容写入发送字符串
            send(sockfd,buf_send,strlen(buf_send),0);
        }
    }
    return 0;
}

服务器server.c

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

#define MAX 50 //定义最大连接人数

//存储客户端地址的结构体数组
struct sockaddr_in client_addr[50];
int client_len = sizeof(client_addr[0]);

//连接后记录confd数组
int confd[MAX] = {};
//连接人数
int count = 0;

void* Talk(void *indexp)
{
    int index = *(int *)indexp;
    int i;
    char buf_recv[200] = {};
    char buf_send[200] = {};

    //读取用户姓名
    char name[20] = {};
    recv(confd[index],name,sizeof(name),0);
    sprintf(buf_send,"%s已加入聊天室\n",name,buf_recv);
    for(i=0;i<=count;++i)
    {
        if(confd[i]==0)
            continue;
        send(confd[i],buf_send,sizeof(buf_send),0);
    }

    while(1)
    {
        bzero(buf_recv,sizeof(buf_recv));//清空缓存字符串
        recv(confd[index],buf_recv,sizeof(buf_recv),0);//读取接收字符串

        //判断是否退出
        if(strcmp("quit",buf_recv)==0)
        {
            sprintf(buf_send,"%s已退出聊天室\n",name);
            //对除退出用户以外所有用户广播退出消息
            for(i=0;i<=count;++i)
            {
                if(i==index||confd[i]==0)
                    continue;
                send(confd[i],buf_send,strlen(buf_send),0);
            }
            confd[index] = 0;
            pthread_exit(0);//结束线程
        }

        //将接收到的字符串复制进发送字符串中
        sprintf(buf_send,"%s\t%s",name,buf_recv);
        for(i=0;i<=count;++i)
        {
            if(i==index||confd[i]==0)
                continue;
            send(confd[i],buf_send,sizeof(buf_send),0);
        }
    }
}

int main(int argc,char **argv)
{
    printf("聊天室服务器端开始运行\n");

    //创建套接字
    int server_sockfd = socket(AF_INET,SOCK_STREAM,0);

    //准备地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;//指定网络套接字
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//接受所有IP地址的连接
    server_addr.sin_port = htons(3898);//绑定到3898端口

    int server_len = sizeof(server_addr);

    //绑定套接字
    bind(server_sockfd, (struct sockaddr*)&server_addr, server_len);

    //设置最大排队数
    listen(server_sockfd,MAX);

    int index;//下标
    while(count < MAX)
    {
        confd[count] = accept(server_sockfd,(struct sockaddr*)&client_addr[count],&client_len);
        ++count;
        index=count-1;

        //创建新线程
        pthread_t tid;
        pthread_create(&tid,NULL,Talk,&index);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值