• 首页

  • 官方

  • 主题

  • 关注

  • 联系

网络编程:Linux平台下聊天室程序的实现

网络编程:Linux平台下聊天室程序的实现

1.直接跳转到Linux端代码


一、实验目的

  1. 学习第18章“多线程服务器端的实现”,掌握线程创建、线程同步的原理和实现方法。
  2. 在Linux操作系统上编写基于多线程的聊天室程序。

二、实验内容

1、在Linux操作系统上编写多线程并发服务器端:
(1)参考第18章相应程序,实现基于多线程的聊天室程序。
(2)为每一个接入的客户端创建线程并适当运用线程同步技术,让多个客户端之间可以交换信息。
(3)启动服务器后创建两个以上客户端并建立连接,验证客户端发送的消息是否可以被所有客户端收到。

Linux端效果图如下:

Linux端的(采用UOS+VScode+g++):
image

Linux端代码如下:

1. 服务器端:
#include<bits/stdc++.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<pthread.h>
#include<unistd.h> 
using namespace std;


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

int sock,i;
int fds[100];//客户端的socketfd,100个元素,fds[0]~fds[99]
static int maxi=0;//maxi表示当前client数组中最大的用户的i值

static int client[10];//最大的在线用户数量

void* recvandsend(void* p){
    int fd = *(int*)p;
    cout<<"客户端:"<<fd<<" 进入聊天室";
    while(1){
        char buf[100] = {};
        if (recv(fd,buf,sizeof(buf),0) <= 0){
            int i;
            for (i = 0;i < 10;i++){
                if (fd == fds[i]){
                    fds[i] = 0;
                    break;
                }
            }
                cout<<fd<<" 已退出!"<<endl;
                pthread_exit(NULL);
        }
        //把服务器接受到的信息发给所有的客户端
        for (int m = 0;m < 10;m++){
        if (fds[m] != 0){
            cout<<buf<<endl;
            send(fds[m],buf,strlen(buf),0);
        }
    }
    }
}
int main()
{
       struct sockaddr_in server_addr;
       int portnumber;
       int thr_id; 

       bzero(client,sizeof(client));//置字节字符串所有字节为零且包括'\0'
 
       //创建套接字

       if((sock=socket(AF_INET,SOCK_STREAM,0))==-1)
       {
              cout<<"套接字连接出错!"<<strerror(errno)<<endl;
              exit(1);
       }

       //设置套接字相关属性

       bzero(&server_addr,sizeof(struct sockaddr_in));
       server_addr.sin_family=AF_INET;
       server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
       server_addr.sin_port=htons(1234);

       /* 捆绑 sock 描述符 */

       if(bind(sock,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
       {
              cout<<"捆绑出错!"<<strerror(errno)<<endl;
              exit(1);
       }
       /* 监听 sock 描述符 */

       if(listen(sock,listennum)==-1)
       {
              cout<<"监听出错!"<<strerror(errno)<<endl;
              exit(1);
       }
       cout<<"欢迎来到戈小戈聊天室^-^"<<endl;
     while(1){
        struct sockaddr_in fromaddr;
        socklen_t len = sizeof(fromaddr);
        int fd = accept(sock,(struct sockaddr *)(&fromaddr),&len);
        if (fd == -1){
            cout<<"客户端连接出错...\n";
            continue;
        }
        for (int i = 0;i < 10;i++){
            if (fds[i] == 0){
                //记录客户端的socket
                fds[i] = fd;
                //有客户端连接之后,启动线程给此客户服务
                pthread_t tid;
                pthread_create(&tid,0,recvandsend,&fd);
                break;
            }
        if (i==10){
            //发送给客户端说聊天室满了
            string str = "聊天室已满!";
            send(fd,&str,sizeof(str),0); 
            close(fd);
        }
        }
    }

}
//g++ 网络编程作业7服务器端.cpp -o test2 -lpthread
2. 客户端:
#include<bits/stdc++.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include<pthread.h>
#include<unistd.h> 
using namespace std; 

static int  sock;

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

{
       char mes[1024];
       int nbytes=0;
       while(1)
       {
              bzero(mes,sizeof(mes));//置字节字符串所有字节为零且包括'\0'
              nbytes=read( sock,mes,sizeof(mes));
              if(nbytes>0)
              {
                     mes[nbytes]='\0';
                     cout<<mes<<endl;
              }
       }
       pthread_exit(NULL);
}

int main()
{
       char buffer[1024];
       struct sockaddr_in  sock_addr;
       char clientname[1024];//客户端昵称
       char mes[1024];
       pthread_t  p_thread;       

       //设置套接字相关属性
       bzero(& sock_addr,sizeof( sock_addr));//置字节字符串所有字节为零且包括'\0'
       sock_addr.sin_family=AF_INET;
       sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
       sock_addr.sin_port = htons(1234);

 
       //创建套接字
       sock = socket(AF_INET,SOCK_STREAM,0);
       if(connect( sock,(struct sockaddr *)(& sock_addr),sizeof(struct sockaddr))==-1)
       {
              cout<<"连接失败!"<<strerror(errno)<<endl;
              exit(1);
       }
       /* 连接成功*/
       cout<<"欢迎来到聊天室"<<endl<<"请输入用户昵称"<<endl;
       fgets(clientname, sizeof( clientname), stdin);
       cout<<endl<<"开始聊天吧(输入Q/q退出聊天室)"<<endl;

       int thr_id =pthread_create(&p_thread, NULL, recvfromserver, NULL);//创建线程

       while(1)
       {
              bzero(buffer,sizeof( buffer));//置字节字符串所有字节为零且包括'\0'
              bzero(mes,sizeof( mes));//置字节字符串所有字节为零且包括'\0'
              fgets(buffer, sizeof( buffer), stdin);
              if(!strcmp(buffer, "q\n") || !strcmp(buffer, "Q\n"))
                     break;    
              strcat(mes,clientname);
              strcat(mes,buffer);
              if((write( sock,mes,strlen(mes)))==-1)
              {
                     cout<<"传输错误!"<<strerror(errno)<<endl;
                     exit(1);
              }        
              
       }

       /* 结束 */
       close(sock);
       exit(0);
}
//g++ 网络编程作业7客户端.cpp -o test1 -lpthread
posted @ 2021-05-21 23:14  戈小戈  阅读(1195)  评论(0编辑  收藏  举报