#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");
}
基于Linux C 用socket和线程 实现的简易聊天室之客户端
最新推荐文章于 2021-05-13 20:47:50 发布