聊天室程序要求
(1)要求实现一个聊天室程序,至少三个客户端可以同时进入聊天室(在服务器开启状态下,客户端随时可进入该聊天室)
(2)服务器程序有日志记录功能,日志中记录每个客户端接入的端口和IP地址以及聊天话术
问题分析
客户端负责发送信息以及接收信息
服务器端负责对客户端发送的信息进行转发,由于是群聊在转发时应当除去发送该信息的客户端
服务器端
/*************************************************************************
> File Name: server_.c
> 作者:YJK
> Mail: 745506980@qq.com
> Created Time: 2019年12月16日 星期一 20时01分10秒
************************************************************************/
#include"hand.h"
#include"aeh.h"
#include"link.h"
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
#define SERV_PORT 5050
#define BACKLOG 5
#define BUFSIZE 150
struct thread_arg{
int new_fd;
LINK head;
int fd2;//重定向到日志文件
};
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
int number = 0;
void *thread_rcv (void *);
int name_lens(const char *); //获取客户端信息中的名字长度
int main(int argc,char *argv[])
{
int fd;
int socket_fd;
struct sockaddr_in sin,cin; //以IPV4方式
struct thread_arg arg;
//日志文件
fd = open("journal",O_RDWR | O_CREAT |O_APPEND, 0777);
if (fd < 0)
err_sys("open");
/* 将标准输出从定向到日志文件*/
close(1);
arg.fd2 = dup2(fd,1);
/* 创建套接字*/
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1)
err_sys("socket");
//绑定 本地IP与端口
/* IP地址快速重用*/
int b_reuse = 1;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int));
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
/* 可绑定在任意IP*/
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(SERV_PORT);
if (bind(socket_fd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
err_sys("bind");
//设置监听
if (listen(socket_fd, BACKLOG) == -1)
err_sys("listen");
int new_fd = -1;
socklen_t len = sizeof(struct sockaddr);
//设置线程的分离属性
int err;
pthread_t tid;
pthread_attr_t tattr;
err = pthread_attr_init(&tattr);
if (err != 0){
err_exit(err, "pthread_attr_init");
}
err = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
if (err != 0){
err_exit(err, "pthread_attr_setdetachstate");
}
LINK head = NULL;
while(1)
{
new_fd = accept(socket_fd, (struct sockaddr *)&cin, &len);
if(ne