聊天室的设计与实现

聊天室的设计与实现

1.实验项目名称:聊天室的设计与实现

2.实验目的:完成局域网内聊天功能,进一步掌握基于socket的编程方法线程创建方法.

3.实验过程:

通过socket 建立用户连接并传送用户输入的信息,分别来写客户端和服务器段,利用多线程来实现多用户模式,服务器随时准备接受客户端发送的消息,并判断该消息类型(私聊或群聊)来进行对应的转发工作,客户端随时接受来自服务器端的消息,从而实现消息的同步

(1)开启服务器

(2)创建用户

(3)群聊的实现

(4)私聊的实现

(5)离开聊天室

ser.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <semaphore.h>#include <pthread.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 8024int i=0;int aa;struct kehu {    char name[10];//记录用户的姓名方便输出及辨认    int haoma;//记录用户连接的sockfd值    } ct[100];//定义发送(拼音)函数,将消息通过结构体中存储的sockfd值发送给所有服务器void fasong(char *qq,int d){    int n=0;    for(n;n<i;n++){    //如果是调用(发送函数)本身的客户端直接跳过,不发送        if(ct[n].haoma==d){        continue;    }    write(ct[n].haoma,qq,strlen(qq));    }}//制作客户端的线程void *cli(void *bb){    int aa=(*(int *)bb);    int sql;    char bk[200];    char bj[200];    char bj1[100];    char bna[100];    char ini[200]={};    char s[10]={"@"};    char *p;    char *pi;    int q;    //先读一遍,接收账户名,发送给其他用户欢迎的提示    read(aa,bna,sizeof(bna));    sprintf(bj1,"欢迎%s进入聊天室",bna);    fasong(bj1,aa);    //名字存入结构体    strcpy(ct[i-1].name,bna);    while(1)    {     q=read(aa,bk,sizeof(bk));         printf("%s\n",bk);         //客户端断开连接时,欢送,释放存储空间         if(q==0){         sprintf(bj,"欢送%s离开聊天室",bna);         fasong(bj,aa);         int u=0;         //循环遍历至断开的客户端位置         for(u;u<i;u++){             if(ct[u].haoma==aa);         break;         }         //将断开位置后的客户端结构体依次向前存储         for(u;u<i;u++){         strcpy(ct[i].name,ct[i+1].name);         ct[i].haoma=ct[i+1].haoma;         }         //将指向创建结构体位置的 i 减一         i-=1;         break;     }          else{       p=bk;       sql=0;           for(p;*p!='\0';p++){           //私聊功能,遍历内容中是否有@来确定是否为私聊           if (*p==*s)           {                int l1=0;        int l2=0;        //以下内容        for(l1;l1<i;l1++){            pi=bk;            for(pi;*pi!='\0';pi++){            if(*pi==*ct[l1].name){                sprintf(bj,"%s对你说%s",bna,bk);                write(ct[l1].haoma,bj,sizeof(bj));                                            break;            }                        }                    }                sql=1;                break;           }         }             //正常聊天      if(sql==1){          continue;      }         sprintf(bj,"%s说:%s",bna,bk);         fasong(bj,aa);              }    }}int main(){    //建立网络连接    int sockfd=socket(AF_INET,SOCK_STREAM,0);    if(sockfd==-1){        perror("failed socket");        exit(-1);        }    printf("网络连接建立成功\n");    //创建结构体    struct sockaddr_in addr;    addr.sin_family=AF_INET;    addr.sin_port=htons(PORT);    inet_aton("127.0.0.1",&addr.sin_addr);    printf("结构体创建成功\n");        //进行连接绑定    int pp=bind(sockfd,(struct sockaddr *)&addr,sizeof(addr));    if(pp==-1){        perror("failed bind");        exit(-1);        }        //建立监听    listen(sockfd,100);    printf("正在初始化\n");    //为连接做定义    struct sockaddr_in from;    socklen_t len = sizeof(from);    int tid[10];        printf("初始化成功\n");    printf("等待连接\n");        //循环等待    while(1){    //等待连接    aa=accept(sockfd,(struct sockaddr *)&from,&len);    //将用户的编号存入结构体    ct[i].haoma=aa;    pthread_t tid[i];    pthread_create(&tid[i],NULL,cli,&aa);    printf("%d号客户端连接成功\n",i);    i+=1;    }}

cli.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <pthread.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 8024int sockfd;//定义一个线程用于读取服务器发来的数据void *rr(void *bb){    while(1){        char ba[200]={0};        int aa=*(int *)bb;        read(aa,ba,sizeof(ba));        printf("%s\n",ba);        }}int main(){    sockfd=socket(AF_INET,SOCK_STREAM,0);    if (sockfd==-1){        perror("failed socket");        exit(-1);    }    struct sockaddr_in addr;    addr.sin_family=AF_INET;    addr.sin_port=htons(PORT);    inet_aton("127.0.0.1",&addr.sin_addr);    connect(sockfd,(struct sockaddr *)&addr,sizeof(addr));    char bk[100];    char bl[100];    char bd[100]={};    printf("*********************\n");    printf("请输入您的账户名\n");    scanf("%s",bk);    printf("*********************\n");    //将用户的账户名发送给服务器    write(sockfd,bk,sizeof(bk));    //通过复制来清空bk的内容    strcpy(bk,bd);    //制作读取线程    pthread_t tid;    pthread_create(&tid,NULL,rr,&sockfd);    //循环读取并发送给服务器    while(1){        scanf("%s",bl);        write(sockfd,bl,sizeof(bl));    }}

4.心得体会

对socket定义及格式,select函数使用有了一定的了解,用socket实现多人聊天的思路,当服务器接收到来自某一客户端的数据时,直接转发给其他所有连接这的客户端,即完成了多人聊天;但是实现聊天室的私聊有bug,当@某人时会将私聊发出的消息再次群发给所有人,需要改进。

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部