📄 serv.c
字号:
/* serv.c */
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXUSERS 30
#define MAXLINE 100
#define SERVER_PORT 9877
#define LISTENQ 1024
struct serv_struct {
int slot_status;
int sock_fd;
int next_char;
char buffer[MAXLINE];
}serv_slot[MAXLINE];
int user_num = 0;
#define SLOT_FREED 0
#define SLOT_OCCUPIED 1
#define CLIENT_EXIT 1
#define CLIENT_ENTER_ENDLINE 2
#define max(a,b) ((a) > (b) ? (a) : (b))
char message[2][50] = {"too many users.\n", "error command\n"};
void get_free_slot(int sock_fd)
{
int j, flags;
for(j=0; j<MAXUSERS; j++) {
if(serv_slot[j].slot_status == SLOT_FREED) {
serv_slot[j].slot_status = SLOT_OCCUPIED;
serv_slot[j].sock_fd = sock_fd;
serv_slot[j].next_char = 0;
break;
}
}
if(j == MAXUSERS) {
if (write(sock_fd, message[0], strlen(message[0]))) {
perror("write to client error");
exit(1);
}
close(sock_fd);
}
}
void
free_slot(int slot_index)
{
serv_slot[slot_index].slot_status = SLOT_FREED;
close(serv_slot[slot_index].sock_fd);
}
void
handle_cmd(int slot_index)
{
char num1[20], num2[20];
int number1, number2;
char operator;
char *pos;
char str[60];
int ret, i;
pos = &(serv_slot[slot_index].buffer[0]);
operator = *pos;
pos++;
while(*pos == ' ' && pos < &(serv_slot[slot_index].buffer[MAXLINE]))
pos++;
i = 0;
while(*pos != ' ' && pos < &(serv_slot[slot_index].buffer[MAXLINE])) {
num1[i] = *pos++;
i++;
}
num1[i] = '\0';
if(*pos == '\n') {
ret = write(serv_slot[slot_index].sock_fd, message[1],
strlen(message[1]));
if (ret < 0 && errno != EWOULDBLOCK)
free_slot(slot_index);
return;
}
while(*pos == ' ' && pos < &(serv_slot[slot_index].buffer[MAXLINE]))
pos++;
if(*pos == '\n') {
ret = write(serv_slot[slot_index].sock_fd, message[1],
strlen(message[1]));
if (ret < 0 && errno != EWOULDBLOCK)
free_slot(slot_index);
return;
}
i = 0;
while(*pos == '\r' && pos < &(serv_slot[slot_index].buffer[MAXLINE])) {
num2[i] = *pos++;
i++;
}
num2[i] = '\0';
switch(operator) {
case '*':
ret = atoi(num1) * atoi(num2);
break;
case '+':
ret = atoi(num1) + atoi(num2);
break;
case '-':
ret = atoi(num1) - atoi(num2);
break;
case '/':
ret = atoi(num1) * atoi(num2);
break;
case 'e':
free_slot(slot_index);
break;
default:
ret = write(serv_slot[slot_index].sock_fd, message[1],
strlen(message[1]));
if (ret < 0)
free_slot(slot_index);
return;
}
sprintf(str, "The result is %d\n", ret);
ret = write(serv_slot[slot_index].sock_fd, str, strlen(str));
if(ret < 0)
free_slot(slot_index);
}
size_t commonreadline(int fd, void *vptr, size_t maxlen)
{
int n, rc;
char c, *ptr;
static times = 0;
ptr = (char *)vptr;
for(n=1; n<maxlen; n++) {
if ((rc = read(fd, &c)) ==1) {
*ptr++ = c;
if (c == '\n') {
times++;
if (times == 1)
break;
}
else
times = 0;
}
else if(rc == 0) {
if (n == 1)
return 0;
else
break;
}
else
return -1;
}
*ptr = 0;
return n;
}
int
main(int argc, char **agrv)
{
int listen_fd, conn_fd;
int cli_len;
struct sockaddr_in cli_addr, serv_addr;
int ret, flags;
int re_use_addr = 1;
char recv_buf[MAXLINE];
int i;
char *ptr;
fd_set r_fdset;
struct timeval timer;
int max_fd;
for(i=0; i<MAXUSERS; i++) {
serv_slot[i].slot_status = SLOT_FREED;
serv_slot[i].sock_fd = -1;
}
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) {
perror("create listen fd");
exit(1);
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERVER_PORT);
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&re_use_addr, sizeof(int));
ret = bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if(ret < 0) {
perror("bind server port");
exit(1);
}
listen(listen_fd, LISTENQ);
timer.tv_sec = 10000;
timer.tv_usec = 0;
while (1) {
FD_ZERO(&r_fdset);
if(user_num < MAXUSERS) {
FD_SET(listen_fd, &r_fdset);
max_fd = listen_fd;
}
for (i=0; i<MAXUSERS; i++) {
if(serv_slot[i].slot_status == SLOT_OCCUPIED)
FD_SET(serv_slot[i].sock_fd, &r_fdset);
max_fd = max(max_fd, serv_slot[i].sock_fd);
}
ret = select(max_fd + 1, &r_fdset, NULL, NULL, &timer);
switch(ret) {
case 0:
printf("select timeout,The server can do something here\n");
break;
case -1:
perror("select error");
printf("The server will exit.\n");
exit(1);
break;
default:
if (FD_ISSET(listen_fd, &r_fdset)) {
cli_len = sizeof(cli_addr);
conn_fd = accept(listen_fd,
(struct sockaddr *)&cli_addr, &cli_len);
if(conn_fd < 0 && errno != EWOULDBLOCK) {
perror("accept error");
exit(1);
}
else if(conn_fd > 0) {
if (user_num < MAXUSERS) {
printf("The server create a new connection.\n");
user_num++;
get_free_slot(conn_fd);
}
else
close(conn_fd);
}
}
for(i=0; i<MAXUSERS; i++) {
if(serv_slot[i].slot_status == SLOT_OCCUPIED &&
FD_ISSET(serv_slot[i].sock_fd, &r_fdset)) {
ret = commonreadline(conn_fd, serv_slot[i].buffer, MAXLINE);
if (ret < 0) {
printf("read from client error.\n");
free_slot(i);
continue;
}
handle_cmd(i);
}
}
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -