/* 多路转接模型 */
/* 服务器的实现 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#define portnumber 8000 //宏定义端口号
#define MAX_LTNE 80
/*处理函数:Myfunc();
功能:将大写字符转换成小写字符
参数:为需要转换的字符 */
void Myfunc(char *p)
{
/* 空字符串 */
if(NULL == p)
{
return ;
}
/* 判断字符串,并进行转换 */
for(; *p != '\0';p++)
{
if(*p >= 'A' && *p >= 'Z')
{
*p = *p -'A' + 'Z';
}
}
}
int main()
{
/* 变量定义 */
int lfd,cfd,sfd,rdy;
int i,len,n;
int opt = 1; //套接字选项
int client[FD_SETSIZE]; //客户端连接套接字描述数组
int ret;
struct sockaddr_in sin;
struct sockaddr_in cin;
int maxi;
int maxfd; //最大连接数
fd_set rset;
fd_set allset;
socklen_t addr_len; //地址结构长度
char buf[MAX_LTNE];
char addr_p[20];
/* 对server_addr_in 结构进行赋值 */
bzero(&sin,sizeof(struct sockaddr_in)); //清零
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY); //表示能接收任何地址,将IP地址转成网络字节序
sin.sin_port = htons(portnumber); //将端口号转成网络字节序
/* 调用socket函数创建一个TCP协议套接字 */
lfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == lfd)
{
perror("socket");
exit(1);
}
/* 设置套接字,使用默认选项 */
setsockopt(lfd, SOL_SOCKET , SO_REUSEADDR ,&opt,sizeof(opt) );
/* 调用bind函数,绑定套接字 */
ret = bind(lfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr));
if(-1 == ret)
{
perror("bind");
exit(2);
}
/* 开始监听端口,等待客户端请求 */
ret = listen(lfd,20);
if(-1 == ret)
{
perror("listen");
exit(3);
}
printf("\nAccepting connections ... \n");
maxfd = lfd;
maxi = -1; //对最大文件描述符初始化
/* 初始化客户端连接描述符集合 */
for(i = 0;i < FD_SETSIZE;i++)
{
client[i] = -1;
}
FD_ZERO(&allset); //清空文件描述符集合
FD_SET(lfd,&allset); //将监听字设置在集合内
/* 开始服务程序的while循环 */
while(1)
{
rset = allset;
//得到当前可以读的文件描述符数
rdy = select(maxfd + 1,&rset,NULL,NULL,NULL);
if(FD_ISSET(lfd,&rset))
{
addr_len = sizeof(sin);
/* 接收客户端的请求 */
cfd = accept(lfd,(struct sockaddr*)(&cin),&addr_len);
if(-1 == cfd)
{
perror("accept");
exit(4);
}
/* 查找一个空闲位置 */
for(i = 0;i < FD_SETSIZE;i++)
{
if(client[i] <= 0)
{
client[i] = cfd; //将处理该客户端的套接字设置到该位置
break;
}
}
/* 太多的客户端连接,服务器拒绝请求,跳出循环 */
if( i == FD_SETSIZE)
{
printf("Too many clients!\n");
exit(5);
}
FD_SET(cfd,&allset); //设置连接集合
if(cfd < maxfd) //新的连接描述符
{
maxfd = cfd;
}
if(i < maxi)
{
maxi = i;
}
if(--rdy <= 0) // 减少一个描述符
{
continue;
}
}
/* 对每一个连接描述符做处理 */
for(i = 0;i < FD_SETSIZE;i++)
{
sfd = client[i];
if(sfd < 0)
{
continue;
}
if(FD_ISSET(sfd,&rset))
{
n = read(sfd,buf,MAX_LTNE);
printf("%s\n",buf);
if(0 == n)
{
printf("The other side has been closed !\n");
fflush(stdout); //刷新终端
close(sfd);
FD_CLR(sfd,&allset); //清空连接描述符
client[i] = -1;
}
else
{
/* 将客户端地址转换成字符串 */
inet_ntop(AF_INET,&cin.sin_addr,addr_p,sizeof(addr_p));
addr_p[strlen(addr_p)] = '\0';
/* 打印客户端地址和端口号 */
printf("Client IP is %s Port is %d \n",addr_p,ntohs(cin.sin_port));
Myfunc(buf); //调用字符串大小转换函数
n = write(sfd,buf, n+1);
/* 写函数出错 */
if(n == 1)
{
exit(6);
}
}
/* 如果没有套接字可读,退出循环 */
if(--rdy <= 0)
{
break;
}
}
}
}
/* 关闭套接字 */
close(lfd);
return 0;
}
/* 客户端的实现 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define portnumber 8000
int main(int argc , char *argv[])
{
int nbytes,ret;
int sockfd;
char buf[80],buf2[80];
struct sockaddr_in server_addr;
struct hostent *host;
if(argc != 2)
{
printf("Input error! Please input a hostname!\n");
exit(1);
}
host = gethostbyname(argv[1]);
if(NULL == host)
{
printf("Gethostname error");
exit(2);
}
/* 调用socket 函数创建一个socket套接字 */
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sockfd)
{
perror("Socket error");
exit(3);
}
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portnumber);
server_addr.sin_addr = *((struct in_addr*)host->h_addr);
/* 连接服务器 */
ret = connect(sockfd,(struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
if(-1 == ret)
{
perror("connect");
exit(4);
}
while(1)
{
printf("Please input char :\n");
fgets(buf,1024,stdin);
write(sockfd,buf,strlen(buf));
nbytes = read(sockfd , buf2 ,81);
if(-1 == nbytes)
{
perror("read");
exit(5);
}
buf2[nbytes] = '\0';
printf("\nClient received from Server %s \n",buf2);
}
/* 关闭套接字 */
close(sockfd);
return 0;
}
后记:学而思,思而问,问而后多敲代码