📄 internet_srv.c
字号:
/* * server.c * Created on: 2008-10-18 * Author: xunzhao * internet domain 通信,服务器端*/#include <stdio.h> #include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <sys/wait.h>#include <netdb.h>#include <stdlib.h>#include <ctype.h>#include <arpa/inet.h>#include <time.h>#include "usock.h"#define port 5120 //服务器监听端口//捕获子进程退出信号,在退出时给出提示信息void sig_handler(int signo){ pid_t pid; int stat; pid = waitpid(-1, &stat, WNOHANG); while(pid > 0){ printf("Child process terminated (PID: %ld) \n",(long)getpid()); pid = waitpid(-1, &stat, WNOHANG); } return ;}int main(int argc, char *argv[]){ int listen_fd,com_fd,ret,on,i; socklen_t len; pid_t pid; time_t timep; struct tm *echo_time; char username[30]; static char snd_buf[1024]; static char recv_buf[1024]; //struct sockaddr_in clt_addr; //struct sockaddr_in srv_addr; struct usock clt_addr; //usock是我自定义的一个结构体,把原来的sockaddr_in结构体作为usock的一个字段 struct usock srv_addr; //并增加一个用户名字段, //我的初衷是实现用户第一次连接服务器时就自动发送用户名 time(&timep); echo_time=localtime(&timep); //获取当地时间 //参数验证 if(argc != 1){ printf("Usage: %s \n", argv[0]); return 1; } //设置信号处理函数,也可以使用sigaction函数 if(signal(SIGCHLD, sig_handler) < 0 ){ perror("Cann't set the signal \n"); return 1; } //创建套接字用于服务器的监听 listen_fd = socket(AF_INET,SOCK_STREAM,0); if(listen_fd < 0){ perror("Cann't creat listening socket!\n"); return 1; } on = 1;//实现地址/端口重用,避免出现Address already in use的错误 ret = setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR, &on, sizeof(on) ); //设置服务器地址参数 memset(&srv_addr, 0, sizeof(srv_addr)); srv_addr.sockaddr.sin_family = AF_INET; srv_addr.sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);//填入本机IP地址 srv_addr.sockaddr.sin_port = htons(port);// //绑定套接字与服务器地址信息 //ret = bind(listen_fd,(struct sockaddr*)&srv_addr, sizeof(srv_addr)); ret=bind(listen_fd,(struct sockaddr*)&srv_addr.sockaddr,sizeof(srv_addr)); if(ret == -1 ){ perror("Cann't bind server socket ! \n"); close(listen_fd); return 1; } //监听指定端口,连接5个客户端 ret = listen (listen_fd,5); if (ret == -1){ perror("Cann't listen the client connect request! \n"); close(listen_fd); return 1; } else puts("服务器启动成功,等待用户登录!\n"); //对每个连接来的客户端创建一个子进程,单独与其进行通信 //首先调用read函数读取客户端发送过来的信息, //将其转换成大写后发送回客户端 //当输入"@"时,程序退出 while(1){ len = sizeof(clt_addr.sockaddr); //printf("This is server ,length of clt_addr is %d \n",len); com_fd = accept(listen_fd,(struct sockaddr*)&clt_addr.sockaddr, &len); if(com_fd > 0){ //printf("This is server,com_fd is %d \n",com_fd); recv(com_fd,username,30,0);//这是我目前采用的获取用户名的方式,客户端连接成功后主动send当前用户名到服务端 //我自定义的usock没能起到预期的作用 } if(com_fd < 0){ if(errno == EINTR){ //printf("EINTR!\n"); continue; }else{ perror("Cann't accept client connect request !\n"); close(listen_fd); return 1; } } time(&timep); echo_time=localtime(&timep); //获取当地时间 printf("用户%s(%s:%d)于%d:%d:%d 登录\n",username,inet_ntoa(clt_addr.sockaddr.sin_addr),ntohs(clt_addr.sockaddr.sin_port),echo_time->tm_hour,echo_time->tm_min,echo_time->tm_sec); pid = fork();//创建子进程,我想在此获得子进程的socket描述符并保存成一个列表,以实现客户端之间的互相通 //printf("after fork,the pid is %d",pid); if (pid < 0 ){ perror("Cannot creat the child process \n"); close(listen_fd); return 1; }else if ( pid == 0 ){ //清空缓存并从客户端读取数据 memset(recv_buf,0,1024); while((len = recv(com_fd,recv_buf,1024,0)) > 0 ) { recv_buf[len] = '\0'; //printf("Message from com_fd: %d\n",com_fd);//这里我的初衷是输入出子进程的socket描述符,但实际上一直输出"4" time(&timep); echo_time=localtime(&timep); //获取当地时间 printf("%s (%d:%d:%d) 说:\n%s",username,echo_time->tm_hour,echo_time->tm_min,echo_time->tm_sec,recv_buf); if(recv_buf[0] == '@' ){ printf("用户%s退出!\n",username); break; } //数据自动处理,进行大小写转换后发送给客户端,也可以设置为服务器端的用户输入,实现聊天 for (i=0; i<len; i++) snd_buf[i] = toupper(recv_buf[i]); snd_buf[len] = '\0'; //发送数据 send(com_fd,snd_buf,len,0); /*write(STDOUT_FILENO,"Server:",8); //从键盘读取用户输入的数据,并写入发送缓存snd_buf memset(snd_buf,0,1024); len=read(STDIN_FILENO,snd_buf,1024); snd_buf[len] = '\0'; send(com_fd,snd_buf,len,0); //这段代码可以实现服务端从键盘读取数据,并发送给客户端,这样就可以自由聊天了 */ } close(com_fd); return 0; }else close(com_fd); }return 0 ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -