当前位置:首页 > > 充电吧
[导读]                            基于linux下的聊天程序设计与实现一、  实现的内容及要求:      用C语言编程实现linux简单的聊天室功能。  用户程序命名为clie

                            基于linux下的聊天程序设计与实现

一、  实现的内容及要求:

      用C语言编程实现linux简单的聊天室功能。


  用户程序命名为client.c;服务器程序命名为server.c  绑定端口等信息见实验方法内容;  要求client可以通过socket连接server  在client,提示输入服务器ip  若连接server 的socket建立成功,返回提示信息  Client输入的聊天内容在client端(多个client端)和server端同时显示;  多个client可同时接入server,进入聊天室,最多支持20个client;  Client端输入quit退出连接,server端提示client退出。  可选择使用多线程实现多客户端;  其他细节见输出结果;


      

二、方法及内容

1.     需要的头文件

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

2.     主要的常量变量

客户端:

#define TRUE 1

#define PORT 5000

int quit=0;     //quit表示是否用户确定退出

 

服务器端:

#define MAXLINE 1000  //在一条消息中最大的输出字符数

#define LISTENQ 20              //最大监听队列

#define PORT 5000               //监听端口

#define MAXFD 20                //最大的在线用户数量

void *get_client(void *);    

int i,maxi=-1;//maxi表示当前client数组中最大的用户的i值

int client[MAXFD];


3.主要模块

客户端:

intmain(void)

void*get_server(void* sockfd)  

//get_server函数,用于接受服务器转发的消息


服务器端:

    intmain() 

    void*get_client(void *sockfd) //运行get_client函数,处理用户请求

 

三.完整代码实现


注:参考socket编程

 

/******* 客户端程序client.c ************/

#include

#include

#include

#include

#include

#include

#include

#include

 

 

#define TRUE 1

#define PORT 5000

 

static int sockfd;

void recvfromserver()        //接受服务器消息线程入口函数

{

       charmes[1024];

       int nbytes=0;

 

       while(1)

       {

              memset(mes,0,sizeof(mes));

              nbytes=read(sockfd,mes,sizeof(mes));

              if(nbytes>0)

              {

                     mes[nbytes]='';

                     printf("%sn",mes);

              }

       }

       pthread_exit(NULL);

}

 

int main(int argc, char *argv[])

{

//     int sockfd;

       charbuffer[1024];

       structsockaddr_in server_addr;

       structhostent *host;

       intportnumber,nbytes;

       charstrhost[16];

       charclientname[20];

       charmes[1024];

       int        thr_id;         /* thread ID for the newly createdthread */

       pthread_t  p_thread;       /* thread's structure                     */

       if(argc!=1)

       {

              fprintf(stderr,"Usage:%san",argv[0]);

              exit(1);

       }

       printf("请输入服务器ip地址n");

       scanf("%s",strhost);

       if((host=gethostbyname(strhost))==NULL)

       {

              fprintf(stderr,"Gethostnameerrorn");

              exit(1);

       }

       /* 客户程序开始建立 sockfd 描述符 */

       printf("正在建立套接口...n");

       if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

       {

              fprintf(stderr,"SocketError:%san",strerror(errno));

              exit(1);

       }

       /* 客户程序填充服务端的资料 */

       bzero(&server_addr,sizeof(server_addr));

       server_addr.sin_family=AF_INET;

       server_addr.sin_port=htons(PORT);

       server_addr.sin_addr=*((structin_addr *)host->h_addr);

       printf("套接口创建成功,正在链接服务器...n");

       /* 客户程序发起连接请求 */

 

       if(connect(sockfd,(structsockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)

       {

              fprintf(stderr,"ConnectError:%san",strerror(errno));

              exit(1);

       }

       /* 连接成功了 */

       printf("链接服务器成功n欢迎来到聊天室n");

       printf("请输入你的用户昵称n");

       scanf("%s",clientname);

//     write(sockfd,clientname,sizeof(clientname));

 

       printf("nn开始聊天吧("Quit"断开连接)nn");

 

 

       thr_id =pthread_create(&p_thread, NULL, recvfromserver, NULL);

       while(1)

       {

              memset(buffer,0,sizeof(buffer));

              memset(mes,0,sizeof(mes));

              scanf("%s",buffer);            

              strcat(mes,clientname);

              strcat(mes,":");

              strcat(mes,buffer);

       //     printf("main thread %sn",mes);

              if((write(sockfd,mes,sizeof(mes)))==-1)

              {

                     fprintf(stderr,"WriteError:%sn",strerror(errno));

                     exit(1);

              }

              if(strcmp(buffer,"Quit")==0)

              {

                     break;

              }

       }

       /* 结束通讯 */

       close(sockfd);

       exit(0);

}

 

/******* 服务器程序(server.c) ************/

#include

#include

#include

#include

#include

#include

#include

#include

 

#define MAXLINE 1000 //在一条消息中最大的输出字符数

#define LISTENQ 20              //最大监听队列

#define PORT 5000               //监听端口

#define MAXFD 20                //最大的在线用户数量

void *get_client(void *);    

int sockfd,i;

static int maxi=0;//maxi表示当前client数组中最大的用户的i值

static int client[MAXFD];

 

void recvandsend(void)           //监听转发线程入口函数

{

       int index=0;

       int nbytes=0;

       charbuffer[1024];

       int len;

       intoutindex=0;

       while(1)

       {

              if(maxi>0)

              {

                     memset(buffer,0,sizeof(buffer));

                     nbytes=0;            

                     //index++;    

                     nbytes=read(client[index++],buffer,sizeof(buffer));

//                   printf("%d,%dn",index,client[index]); 

                     if(nbytes>0)

                     {

                            buffer[nbytes]='';

                            printf("%sn",buffer);

                            outindex=0;

                            while(outindex<maxi)

                                   if(write(client[outindex++],buffer,sizeof(buffer))==-1)

                                   {

                                          fprintf(stderr,"WriteError:%sn",strerror(errno));

                                          exit(1);

                                   }

                     }

              }

              if(index>=maxi)

                     index=0;

       }

       pthread_exit(NULL);

}

 

int main(int argc, char *argv[])

{

//     intclient_fd[LISTENQ],clientnum=0;;

       structsockaddr_in server_addr;

       structsockaddr_in client_addr;

       intsin_size,portnumber;

       charhello[]="Hello! Are You Fine?n";

       int        thr_id;         /* thread ID for the newly createdthread */

       pthread_t  p_thread;       /* thread's structure                     */

       int new_fd=0;

       memset(client,0,sizeof(client));

       if(argc!=1)

       {

              fprintf(stderr,"Usage:%sportnumberan",argv[0]);

              exit(1);

       }

 

       /* 服务器端开始建立 socket 描述符 */

       if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

       {

              fprintf(stderr,"Socketerror:%sna",strerror(errno));

              exit(1);

       }

       /* 服务器端填充 sockaddr 结构 */

       bzero(&server_addr,sizeof(structsockaddr_in));

       server_addr.sin_family=AF_INET;

       server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

       server_addr.sin_port=htons(PORT);

       /* 捆绑 sockfd 描述符 */

       if(bind(sockfd,(structsockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)

       {

              fprintf(stderr,"Binderror:%sna",strerror(errno));

              exit(1);

       }

       printf("服务器监听端口%d...n",PORT);

       /* 监听 sockfd 描述符 */

       if(listen(sockfd,LISTENQ)==-1)

       {

              fprintf(stderr,"Listenerror:%sna",strerror(errno));

              exit(1);

       }

       thr_id =pthread_create(&p_thread, NULL, recvandsend, NULL);

       printf("欢迎来到本聊天室n");

       while(1)

       {

              /* 服务器阻塞,直到客户程序建立连接 */

              if(maxi>=20)

              {

                     printf("以达到人数上线n");

                     continue;

              }

              sin_size=sizeof(structsockaddr_in);

              if((new_fd=accept(sockfd,(structsockaddr *)(&client_addr),&sin_size))==-1)

              {

                     fprintf(stderr,"Accepterror:%sna",strerror(errno));

                     exit(1);

              }

              /*fprintf(stderr,"Serverget connection from %sn",inet_ntoa(client_addr.sin_addr));*/

              client[maxi++]=new_fd;

              printf("n新用户进入聊天室%dn",new_fd);      

       }

       close(sockfd);

       exit(0);

}

      

四、测试结果显示

1.     执行结果

l  服务器打开



l  客户端打开,并输入了地址,昵称



l  服务器端显示



l  客户端2进入



l  服务器显示



l  张三输入



l  李四端显示



l  服务器显示



l  李四输入



l  张三显示



l  服务器显示



2.     结果分析

       这是一个聊天室程序,可以实现群聊的功能,即当某个客户发出消息后,服务器和其他个客户端都能收到此消息。且能够显示客户端的用户名。但客户端退出聊天室后,服务器和其他在线客户端会有提示。

       实现群聊的机制是:当某个客户端需要发送消息是,它将此消息发送给服务器,服务器再将此消息转发给各客户端,各客户端之间是无连接的,即相互之间不能直接通信。因此,在服务器中,有两个线程,主线程用来监听是否有客户端登录服务器,若有,建立与其连接的套接字,并存入在线客户序列里,辅助线程是接收转发线程,其依次读取个客户端,看是否有消息送达,若有,取出,并转发给各其他客户端。在客户端也有两个线程,主线程用来向服务器发送消息,辅助线程用来接收服务器发出的消息。

        存在的问题是:1.当有用户下线是,虽会在服务器和各客户端提示用户下线,但是并未删除其在服务器中的套接字,致使后来用户不能进入。2.服务器的辅助线程对各客户端采取轮流监听的策略,但是因为使用read() 函数会阻塞线程,致使出现各客户端必须按登陆顺序依次发言的尴尬情况。经过查找,可以使用select()函数跨过阻塞,正在试验中。


            不足之处,欢迎指正!欢迎交流!


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭