基于Linux C 用socket和线程 实现的简易聊天室之客户端

5 篇文章 1 订阅
1 篇文章 0 订阅

#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("请正确输入ID\n", 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是:  %d\t 密码是:%s\n",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 = %d\n",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("%s\n",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("%s\n",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 = %d\n",file_block_length);

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


strcpy( buffer_file , "END");
printf("client (发送) buffer is %s\n", buffer_file);
if(send(socket_fd, buffer_file, 10, 0) < 0)
{
printf("发送失败2\n");
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 = %d\n",msg_accept.num_s[i]);

}

break;
}
case 4:
  { 
   sleep(1);
                printf("查询成功,有这个ID,他的客户端为 : %d\n",msg_accept.id_s);
break;
}
            case 5:
{    
   sleep(1);
printf("查询失败,没有这个ID\n");
break;
}
            case 7:
{
sleep(1);
printf("ID为%d的人给你发来消息,消息是:%s\n",msg_accept.id_s,msg_accept.name_s);
break;
}
            case 8:
{
                sleep(1);
                printf("你的消息已发送成功\n");
                break;
 
}
   case 9:
{
sleep(1);
printf("ID为%d的人给发来了群聊消息,消息是 : %s\n",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的人给你发来了文件,文件名是 :%s\n",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("%s\n",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");


}







 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值