实验要求
- 用户默认处于广播模式,一个客户在其客户端发送的消息,其它客户端用户全部可以收到;
- 程序支持下列命令
/help:显示帮助信息(思考:信息是放在客户端还是服务器端);
/quit:用户退出聊天室,同时将退出信息广播给其他用户;
/who:显示在线用户;
/send 用户名 消息:向指定用户发送点到点消息 - 程序退出时清理所有的占用资源,包括内存资源、套接字等
- 支持最大连接数限制;
- 能够管理用户加入和退出。
实验环境
Red Hat 9
代码
chatserver.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netdb.h>
#include<sys/time.h>
#include<sys/types.h>
#define PORT 1573
#define BACKLOG 10
#define BUFSIZE 2048
struct client_info{
int id; //Represents the socket the user is now accessing
char name[256];
int first; //whether the user is visiting for the first time and is used to pass in the name
};
int main(){
fd_set allset; //All sockets that need to be scanned
fd_set rset; //Socket after select
struct sockaddr_in server;
struct sockaddr_in client;
int maxfd;
int sockfd;
int confd;
char recvbuf[BUFSIZE];
char sendbuf[BUFSIZE];
int recvnum;
int sendnum;
int opt; //Define socket properties
int length;
opt = SO_REUSEADDR;
length = sizeof(struct sockaddr);
int tmp_i;
int tmp_j;
char str1[256];
char str2[256];
char str3[256];
int tmpid=-1;
int tmpfd=-1;
struct client_info clientinfo[BACKLOG];
FD_ZERO(&allset);
FD_ZERO(&rset);
if(-1 == (sockfd=socket(AF_INET,SOCK_STREAM,0)))
{
perror("create socket error!\n");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
memset(&server,0,sizeof(server));
memset(sendbuf,0,BUFSIZE);
memset(recvbuf,0,BUFSIZE);
int i;
for(i=0;i<BACKLOG;i++)
{
clientinfo[i].id = -1;
clientinfo[i].name[0] = '\0';
clientinfo[i].first = -1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(PORT);
if(-1 == bind(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr)))
{
perror("bind socket error!\n");
exit(1);
}
if(