⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 internet_srv.c

📁 linux系统下的socket源码
💻 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 + -