我是靠谱客的博主 自由洋葱,最近开发中收集的这篇文章主要介绍基于Linux C 用socket和线程 实现的简易聊天室之客户端,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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


#define PORTNUMBER 9994
#define OK 1
#define ERROR 0


//判断在线情况标识符,1表示在线正常,2表示被踢下线,3表示被禁言
int *adress_online;


typedef  int Elementtype; 
typedef  int Status;  


//定义一个客户端的结构体
typedef struct client
{
Elementtype id;
Elementtype flag;
Elementtype case_num;//功能选择
Elementtype case_numnext;//发送登录成功聊天功能选择
char name[100];//名字
    char password[150];//密码
//char content_c[1024];//发送客户端消息


}Client_message;


//定义一个与服务器一致的结构体
typedef struct server
{
Elementtype i_s; 
    Elementtype num_s[10];

Elementtype case_snum;//接收服务器进行的功能选择
Elementtype id_s;
char name_s[100];
    char password_s[150];
//char content_s[1024];//接收服务器发送的消息缓存区

}Server_message;




Client_message msg_send;  //定义一个全局的客户端结构体,发送客户端的结构体
Server_message msg_accept;  //定义一个全局的客户端结构体,用于接收服务器的结构体


void *func(void *arg);


int main(int argc, char *argv[])
{   
    int ret;
system("clear");

printf("正在启动客户端......n");
sleep(2);


if (argc != 2)
{
printf("请正确输入IDn", argv[0]);
exit(0);
}

int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_fd)
{
perror("建立通信失败");
exit(1);
}

struct sockaddr_in client_addr;


memset(&client_addr, 0, sizeof(client_addr));

client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(PORTNUMBER);
client_addr.sin_addr.s_addr = inet_addr(argv[1]);

if (-1 == connect(socket_fd, (struct sockaddr *)(&client_addr), sizeof(struct sockaddr)))
{
perror("连接服务器失败");
exit(2);
}
printf("客户端启动成功......n");
sleep(2);
printf("连接服务器成功......n");

char buff[1024] = {0};
    char sendbuff[1024] = {0};

pthread_t pid;//创建一个线程

while(1)
{
printf("---------------欢迎来到聊天室---------------n");
   printf("---------------请选择以下功能---------------n");
   printf("-----------------1. 注册--------------------n"); 
        printf("-----------------2. 登录--------------------n");
   printf("-----------------3. 退出--------------------n");
   printf("--------------------------------------------n");
printf(">>>>>>>>>>>>>>请输入数字1 ~ 3: <<<<<<<<<<<<n");

scanf("%d",&msg_send.case_num);

        switch(msg_send.case_num)
        {
 
             case 1:
{        
            
                 char password_temp[20] = {0};  
    
            printf("请输入你要注册的名字:n");
scanf("%s",&msg_send.name);

printf("请输入你注册的密码:n");
scanf("%s",&msg_send.password);
 
printf("请再次输入你注册的密码:n");
scanf("%s",&password_temp);
 
if(strcmp(msg_send.password,password_temp) != 0)
{   
        printf("---------------------------------n");
                     printf("两次输入的密码不一样,请重启注册.n");
printf("---------------------------------n");
                     break;    
}
//else
//{
// msg_send.case_num = 1;


memset(sendbuff,0,1024);
    memcpy(sendbuff,&msg_send,sizeof(msg_send));
    
    ret = write(socket_fd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(1);
}
printf("你的注册信息已发送到服务器,请等待......n");
sleep(2);
                     
memset(buff,0,1024);
    ret = read(socket_fd, buff, 1024);
    if(-1 == ret)
    {
    perror("接收服务器的消息失败");
    exit(1);
    }                  
 
memset(&msg_accept,0,sizeof(msg_accept));
    memcpy(&msg_accept, buff, sizeof(msg_accept));
 
if(msg_accept.case_snum == 0)
{   
        printf("---------------------------------------------------------n");
printf("恭喜你注册成功.你的登录的ID是:  %dt 密码是:%sn",msg_accept.id_s,password_temp);
printf("---------------------------------------------------------n");
 
memset(&msg_send,0,sizeof(msg_send));
                         memset(&msg_accept,0,sizeof(msg_accept));
 
break;
}  
else
{
printf("不好意思,你注册失败了.n");
 
memset(&msg_send,0,sizeof(msg_send));
                         memset(&msg_accept,0,sizeof(msg_accept));
 
break;

                 
                // }
 
}
case 2:

 
memset(sendbuff,0,1024);
 
    printf("请输入你要登录的ID:n");
scanf("%d",&msg_send.id);

printf("请输入你登录的密码:n");
scanf("%s",&msg_send.password);
 
//msg_send.case_num = 2;
                 
                 //把ID和密码发到服务器
memcpy(sendbuff,&msg_send,sizeof(msg_send));

ret = write(socket_fd ,sendbuff, 1024);
                 if(-1 == ret)
                 {
                     perror("写入失败");
                     exit(2);
                 }
                 printf("登录信息已发送到服务器,请稍等......n");                 
                 
 
                 memset(buff,0,1024);  
ret = read(socket_fd, buff, 1024);//读取服务器发送的消息
if(-1 == ret)
{
perror("接收服务器的消息失败");
exit(1);
}                  
 
memcpy(&msg_accept, buff, sizeof(msg_accept));//把服务器传过来的套接字转换为结构体
 
//printf("msg_accept.case_snum = %dn",msg_accept.case_snum);
if(msg_accept.case_snum == 2)//普通用户登录
{
                     printf("恭喜你普通用户登录成功.n");
 
int online = 1;
adress_online = &online;
//创建一个线程读出服务器发过来的消息
 
ret = pthread_create(&pid, NULL,(void* )func, (void *)socket_fd);
if(-1 == ret)
{
    perror("创建线程失败");
exit(1);
}


while(1)
{
    printf("---------------请选择以下功能---------------n");
printf("-----------------1.查看当前在线人数---------n"); 
printf("-----------------2.私聊---------------------n");
printf("-----------------3.群聊---------------------n");
printf("-----------------4.发送文件-----------------n");
                printf("-----------------5.注销---------------------n");
                         printf(">>>>>>>>>>>>>>请输入数字1 ~ 5: <<<<<<<<<<<<n");
 
scanf("%d",&msg_send.case_numnext);//登录成功后发送到服务器的请求

if(2 == online)
{
    goto out;//完成踢人操作
}
 

                         switch(msg_send.case_numnext)
                         {
                              case 1:
 {   
 memset(sendbuff, 0, 1024);
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 
 printf("已经向服务器发送请求,求稍等......n");
 sleep(2);
 /*
             memset(buff,0,1024);
                 ret = read(socket_fd, buff, 1024);
                 if(-1 == ret)
                 {
                 perror("接收服务器的消息失败");
                 exit(1);
                 }                  


 printf("%sn",buff);
 */
 
 break;
 }
 case 2:
 {
           
 if(3!= online)
 {
 memset(sendbuff, 0, 1024);

 printf("请输入你想要私聊的ID:n");
 scanf("%d",&msg_send.id);
 
 printf("请输入你想要私聊的内容:n");
 scanf("%s",&msg_send.name);//把名字暂时作为传过去内容的存储区域
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
 perror("写入失败");
 exit(1);  
 }
 printf("已经向服务器发送请求,正在查询有无此ID,请稍等......n");
   
 sleep(2);
 break;   
 }
 
                                  else
 {
                                      printf("小伙子不好意思你被管理员禁言了n");
 break;
 }
 
 break;
 }
 case 3:
 {
 if(3 != online)
 {
 memset(sendbuff, 0, 1024);

 printf("请输入你想要群聊的内容:n");
 scanf("%s",&msg_send.name);//把名字的区域暂时作为传过去内容的存储区域
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
 perror("写入失败");
 exit(1);  
 }
 printf("已经向服务器发送请求,正在发送群聊消息,请稍等......n");
 
 sleep(2);
 break;
     }
 
                                  else
                                  {
                                       printf("小伙子不好意思你被管理员禁言了n");
  break;
 }
 
                                  break;  
 }
 case 4:
 {   
     
 if(3 != online)
 {
 //先把名字发过去
 memset(sendbuff, 0, 1024);
 
 printf("请输入接收文件人ID:n");
 scanf("%d",&msg_send.id);
 
 printf("请输入你发送文件的名字:n");
 scanf("%s",&msg_send.name);
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
 perror("写入失败");
 exit(1);  
 }
 
 
 //再把内容发过去,创建一个与上面一样的名字
 FILE *file = fopen(msg_send.name,"r");
 if(NULL == file)
 {
 perror("打开失败");
 exit(1);
 }
 
 int length = 0;
 char content[1024] = {0}; 

 
 //测试要发送内容的长度
                 length = fread(content, sizeof(char), 1024, file);
 if(length <= 0)
 {
 perror("测试长度失败");
 exit(1);
 }
 
 
 //把内容写到socket_fd
 send(socket_fd,content,length,0);
 
 close(file);
 
 printf("文件已发送成功,等待服务器的处理n");
 
 sleep(2);
 
 break;
        
         }
 
                                  else
                                  {
                                       printf("小伙子不好意思你被管理员禁言了,不能发送文件n");
  break;
 }
 
 break;
 }


 case 5:
     {
 memset(sendbuff, 0, 1024);
 char str_temp[10];
 
 printf("你是否想要下线 ?输入: yes 确定下线 ,输入: no 撤回请求 n");
 scanf("%s",&str_temp);
 
 if(strcmp(str_temp, "yes") == 0)
 {
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
 perror("写入失败");
 exit(1);  
 }
 printf("已经向服务器发送下线请求,请稍等......n");

                                      goto out;   
 }
 
                                  else
 {
 break;
 }
     
 
 //break;
 
 }
 
                         }  
  
                     }  


break;
}  
                 
                 if(msg_accept.case_snum == 1)  //登录失败
                 {
                     printf("登录信息有误,请重新登录...n");
memset(&msg_send,0,sizeof(msg_send));
memset(&msg_accept,0,sizeof(msg_accept));
break;
}
 
 
                 if(msg_accept.case_snum == 3)//管理员登录
          {
                     printf("恭喜你管理员登录成功n");

ret = pthread_create(&pid, NULL,(void* )func, (void *)socket_fd);
if(-1 == ret)
{
    perror("创建线程失败");
exit(1);
}
 
while(1)
{
    printf("----------管理员你好,请选择以下功能----------n");
printf("-----------------1.查看当前在线人数----------n"); 
printf("-----------------2.私聊----------------------n");
printf("-----------------3.群聊----------------------n");
printf("-----------------4.发送文件------------------n");
                printf("-----------------5.注销----------------------n");
printf("-----------------6.禁言----------------------n");
printf("-----------------7.解禁----------------------n");
                         printf("-----------------8.踢人----------------------n");
                         printf(">>>>>>>>>>>>>>请输入数字1 ~ 8: <<<<<<<<<<<<<n");
 
scanf("%d",&msg_send.case_numnext);
 
                         switch(msg_send.case_numnext)
                         {
                              case 1:
 {   
 memset(sendbuff, 0, 1024);
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 
 printf("已经向服务器发送请求,求稍等......n");
 
 /*
             memset(buff,0,1024);
                 ret = read(socket_fd, buff, 1024);
                 if(-1 == ret)
                 {
                 perror("接收服务器的消息失败");
                 exit(1);
                 }                  


 printf("%sn",buff);
 */
 
 break;
 }
 case 2:
 {
 
 memset(sendbuff, 0, 1024);

                                  printf("请输入你想要私聊的ID:n");
 scanf("%d",&msg_send.id);
                                 
 printf("请输入你想要私聊的内容:n");
 scanf("%s",&msg_send.name);//把名字暂时作为传过去内容的存储区域
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 printf("已经向服务器发送请求,正在查询有无此ID,请稍等......n");
 
 
 break;
 }
 case 3:
 {
 memset(sendbuff, 0, 1024);

 printf("请输入你想要群聊的内容:n");
 scanf("%s",&msg_send.name);//把名字的区域暂时作为传过去内容的存储区域
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 printf("已经向服务器发送请求,正在发送群聊消息,请稍等......n");
 
 break;
 }
 case 4:
 {
 //先把名字发过去
     memset(sendbuff, 0, 1024);
 
 printf("请输入接收文件人ID:n");
 scanf("%d",&msg_send.id);
 
 printf("请输入你发送文件的名字:n");
 scanf("%s",&msg_send.name);
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
 exit(1);  
 }
 
 
 //再把内容发过去,创建一个与上面一样的名字
 FILE *fp = fopen(msg_send.name,"r");
 if(NULL == fp)
 {
       perror("打开失败");
 exit(1);
 }
 
 else
 {
char buffer_file[1024];
memset(buffer_file, 0, 1024);
int file_block_length = 0;
while( (file_block_length = fread(buffer_file, sizeof(char), 1024, fp)) > 0)
{
printf("length = %dn",file_block_length);

if(send(socket_fd, buffer_file, file_block_length, 0) < 0)
{
printf("发送失败1n", msg_send.name);
break;
}
memset(buffer_file, 0, 1024);
}        
fclose(fp);


strcpy( buffer_file , "END");
printf("client (发送) buffer is %sn", buffer_file);
if(send(socket_fd, buffer_file, 10, 0) < 0)
{
printf("发送失败2n");
break;
}

}


 break;
 
 }


 case 5:
     {
 memset(sendbuff, 0, 1024);
 char str_temp[100];
 
 printf("你是否想要下线 ?输入: yes 确定下线 ,输入: no 撤回请求 n");
 scanf("%s",&str_temp);
 
 if(strcmp(str_temp, "yes") == 0)
 {
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
 perror("写入失败");
 exit(1);  
 }
 printf("已经向服务器发送下线请求,请稍等......n");
 
                                     
 goto out;  
 }
                                  else
 {
 break;
 }
     
 //break;
 
 }
 case 6 ://禁言
 {
 memset(sendbuff, 0, 1024);

 printf("请输入你想要禁言的ID:n");
 scanf("%d",&msg_send.id);
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 printf("已经向服务器发送请求, 请稍等......n");

 break;
 
 
 }
 case 7://解禁
 {
 memset(sendbuff, 0, 1024);

 printf("请输入你想要解禁的ID:n");
 scanf("%d",&msg_send.id);
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 printf("已经向服务器发送请求,请稍等......n");
 

 break;
 }
 
 case 8://踢人下线
 {
 
 memset(sendbuff, 0, 1024);

 printf("请输入你想要踢人的ID:n");
 scanf("%d",&msg_send.id);
 
 memcpy(sendbuff, &msg_send, sizeof(msg_send));
 
 ret = write(socket_fd, sendbuff, sizeof(sendbuff));
 if(-1 == ret)
 {
     perror("写入失败");
                                     exit(1);  
 }
 printf("已经向服务器发送请求,请稍等......n");

 }
 
                         }  
  
                     }  


                     break;  
}  
 
 
break;
}
 
case 3://退出程序
{
 
memset(sendbuff, 0, 1024);//清空发送缓存
memcpy(sendbuff, &msg_send, sizeof(msg_send)); //结构体转换成字符串

ret = write(msg_send, sendbuff, 1024);//发送信息
if(-1 == ret)
{
perror("写入失败");
exit(1);
}
   
                 goto outroom;  
  }


}




out : 
printf("----------n"); 

}

    outroom :

close(socket_fd);


return 0;
}




void *func(void *arg)
{
int ret;
int socket_fd = (int)arg;
char buff[1024] = {0};

while(1)
{

ret = read(socket_fd, buff, 1024);//把服务器传来的消息读到buff
if(-1 == ret)
{
perror("读取服务器失败");
exit(1);
}

memset(&msg_accept, 0, sizeof(msg_accept));//清空结构体
memcpy(&msg_accept, buff, sizeof(msg_accept));//把接收到的信息转换成结构体

switch(msg_accept.case_snum)
{
case 6: //查询在线人数
{
sleep(1);
printf("在线人数为 : %d ,分别为如下 :n",msg_accept.id_s);

int i;

for(i = 0;i < msg_accept.i_s;i++)
{
   printf("ID = %dn",msg_accept.num_s[i]);

}

break;
}
case 4:
  { 
   sleep(1);
                printf("查询成功,有这个ID,他的客户端为 : %dn",msg_accept.id_s);
break;
}
            case 5:
{    
   sleep(1);
printf("查询失败,没有这个IDn");
break;
}
            case 7:
{
sleep(1);
printf("ID为%d的人给你发来消息,消息是:%sn",msg_accept.id_s,msg_accept.name_s);
break;
}
            case 8:
{
                sleep(1);
                printf("你的消息已发送成功n");
                break;
 
}
   case 9:
{
sleep(1);
printf("ID为%d的人给发来了群聊消息,消息是 : %sn",msg_accept.id_s,msg_accept.name_s);
break;
}
case 10:
{
sleep(1);
printf("你的群聊消息已发送成功n");
   break; 
}
case 11:
{
sleep(1);
printf("你已经下线成功n");
   goto out_1;
  // break;
}
case 12:
{
sleep(1);
printf("小伙子不好意思你被管理员禁言了n");
   *adress_online = 3;
break;
}
case 13:
{
sleep(1);
printf("禁言成功了n");
break;

}
case 14:
{
sleep(1);
printf("小伙子运气不错,你被管理员解禁了n");
   *adress_online = 1;
break;

}
case 15:
{  
   sleep(2);
printf("解禁成功,他又可以说话了n");
break;
}
       case 16:
{

printf("小伙子不好意思你被管理员踢出去了n");

char sendbuff_temp[1024] = {0};
msg_send.case_numnext = 5;
memcpy(sendbuff_temp, &msg_send, sizeof(msg_send)); //结构体转换成字符串

ret = write(socket_fd, msg_send, 1024);//发送信息
if(-1 == ret)
{
perror("写入失败");
exit(1);
}
   
                
                *adress_online = 2;
break;

}
         case 17:
{
                sleep(1);
printf("踢人操作成功n");

break;

}
            case 18://文件传输
            {

                printf("ID为: %d的人给你发来了文件,文件名是 :%sn",msg_accept.id_s,msg_accept.name_s);
                
char buffer_file[1024];
char str[20];

                printf("请输入你要另存文件的名字:n");
scanf("%s",&str);

FILE * fp = fopen(str,"w");
if(NULL == fp )
{
perror("打开失败"); 
exit(1);
}

memset(buffer_file, 0, 1024);

int length = 0;
while(1)
{
length = read(socket_fd, buffer_file, 1024);
if(length < 0)
{
perror("读入失败");
break;
}

printf("内容是 : n");
printf("%sn",buffer_file);

if(0 == strncmp(buffer_file, "END", 3))
{
printf("文件接收完成n");
break;

}

int write_length = fwrite(buffer_file, sizeof(char), length, fp);
if(write_length < length)
{
perror("写入失败");
break;
}

}

fclose(fp);

                
break;
}


            case 19:
            {
                sleep(1);
printf("发送成功");
                break;


}
        }




    }

out_1:
printf("----------n");


}







 

最后

以上就是自由洋葱为你收集整理的基于Linux C 用socket和线程 实现的简易聊天室之客户端的全部内容,希望文章能够帮你解决基于Linux C 用socket和线程 实现的简易聊天室之客户端所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部