head.h
#ifndef __HEAD_H
#define __HEAD_H
// 常用头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 网络编程涉及的头文件
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
// 本机字节序和网络字节序转换相关函数的头文件
#include <arpa/inet.h>
// 关闭套接字用close函数需要的头文件
#include <unistd.h>
//线程相关的函数头, mutex相关的函数
#include <pthread.h>
// 类型重命名:地址结构体的规范
typedef struct sockaddr SockAddr;
// 地址结构体的规范的实现结构体
typedef struct sockaddr_in SockAddrIn;
// if_nametoindex
#include <net/if.h>
#include <sys/select.h>
#include <sys/time.h>
// JSON字符串的封装
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 文件操作需要的头文件
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <mysql/mysql.h>
// selet
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
// 定义外部变量
//int sockfdNUM[10] = {0};
#endif
p_char.h
#ifndef _P_CHAT_H
#define _P_CHAT_H
#define BUF_SIZE 1024
#include "head.h"
// 错误处理函数,用于输出错误信息并终止程序
void error_handling(const char *message);
#endif
p_chat.c
#include "p_chat.h"
// 私聊接收任务函数
void *s_private_chat(void *arg)
{
// 1.获取客户端套接字
int sock = *(int *)arg;
char buf[1024] = {0};
while (1)
{
scanf("%s", buf);
send(sock, buf, strlen(buf), 0);
if (strcmp(buf, "quit") == 0)
{
break;
}
memset(buf, 0, sizeof(buf));
}
// 关闭服务端套接字
close(sock);
exit(0); // 结束整个线程
}
void *r_private_chat(void *arg)
{
// 1.获取客户端套接字
int sock = *(int *)arg;
char buf[1024] = {0};
while (1)
{
recv(sock, buf, sizeof(buf), 0);
printf("%s\n", buf);
memset(buf, 0, sizeof(buf));
}
// 关闭服务端套接字
close(sock);
}
// 客户端
int main(int argc, char const *argv[])
{
// 创建线程id
pthread_t tid1;
pthread_t tid2;
// 1.创建socket
int s_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == s_sockfd)
{
perror("socket failed");
return -1;
}
// 2.绑定地址
SockAddrIn serverAddr;
// ipv4协议
serverAddr.sin_family = AF_INET;
// 端口
serverAddr.sin_port = htons(8888);
// ip地址
serverAddr.sin_addr.s_addr = inet_addr("192.168.118.129");
// 创建一个用于存放的json字符的数组
char *jsonString;
// 3.连接服务器
int ret = connect(s_sockfd, (SockAddr *)&serverAddr, sizeof(serverAddr));
if (-1 == ret)
{
perror("connect failed");
return -1;
}
// 4.1 接收服务器消息
char buf[2048] = {0};
ret = recv(s_sockfd, buf, sizeof(buf), 0);
if (-1 == ret)
{
perror("recv failed");
return -1;
}
int uid, fid;
uid = atoi(argv[1]);
fid = atoi(argv[2]);
printf("uid = %d\n", uid);
printf("fid = %d\n", fid);
printf("s_sockfd = %d\n", s_sockfd);
// 判断上一个进程传来的数据
if (strcmp(argv[3], "私聊") == 0)
{
// 向服务端发送自己的状态
int stat = 1;
send(s_sockfd, &stat, sizeof(stat), 0);
// 私聊
// 发送uid
send(s_sockfd, &uid, sizeof(uid), 0);
// 发送fid
send(s_sockfd, &fid, sizeof(fid), 0);
//puts("待接收历史消息");
// 清空buf
memset(buf, 0, sizeof(buf));
// 接收聊天记录
recv(s_sockfd, buf, sizeof(buf), 0);
//puts("历史消息接收完毕:");
puts(buf);
puts("以上是历史消息");
// 创建线程
pthread_create(&tid1, NULL, s_private_chat, &s_sockfd);
pthread_create(&tid2, NULL, r_private_chat, &s_sockfd);
// 等待线程结束
pthread_join(tid1, NULL);
}
else if (strcmp(argv[3], "群聊") == 0)
{
// 向服务端发送自己的状态
int stat = 2;
send(s_sockfd, &stat, sizeof(stat), 0);
// 公屏聊天
// 发送uid
send(s_sockfd, &uid, sizeof(uid), 0);
puts("开始聊天");
// 创建线程
pthread_create(&tid1, NULL, s_private_chat, &s_sockfd);
pthread_create(&tid2, NULL, r_private_chat, &s_sockfd);
// 等待线程结束
pthread_join(tid1, NULL);
}
// 5.关闭socket
close(s_sockfd);
puts("关闭socket");
return 0;
}
makefile
SRCS = $(wildcard *.c)
OBJS = $(patsubst *.c,*.o,$(SRCS))
CC = gcc
TARGET = p_chat
LDFLAGS = -lpthread -lmysqlclient
.PHONY : clean
$(TARGET) : $(OBJS)
$(CC) $^ -o $@ $(LDFLAGS)
clean :
rm *.o
run :
./$(TARGET)
show :
echo $(SRCS) / $(OBJS)