前几天帮同学写了一个十分简单的基于linux I/O 复用的计算程序,由于应用层协议的设计,只能实现个位数字的四则运算。有需要的可以修改应用层协议。
运行截图:
服务端程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/select.h>
#include<time.h>
#define len 1024
//错误信息输出
void error_hangling(char* message){
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
//计算函数(可以通过改善该函数实现对计算程序的增强,输入的是单字节字符流)
int calculate(char* messages,int str){
int str_len =str-1;
int a[str_len];
char b[str_len];
int opnum=0,num=0;
int result;
//将数字和运算符分别存储
for(int i =0 ;i<str_len;++i){
if(48<=messages[i] && messages[i]<=57){
a[i] = messages[i]-48;
num++;
}
else{
b[i] = messages[i];
++opnum;
}
}
for(int i=0;i<opnum;++i){
int false =0;
// * 运算符
for(int j=0;j<str_len;++j){
if(b[j]=='*' && false == 0){
false = 1;
if(i== opnum-1){
result=a[j-1]*a[j+1];
}
else{
int tmp = a[j-1]*a[j+1];
a[j-1]=tmp;
a[j+1]=tmp;
b[j]='#';
}
break;
}
}
// / 运算符
for(int j=0;j<str_len;++j){
if(b[j]=='/'&& false == 0){
false = 1;
if(i== opnum-1){
result=a[j-1]/a[j+1];
}
else{
int tmp = a[j-1]/a[j+1];
a[j-1]=tmp;
a[j+1]=tmp;
b[j]='#';
}
break;
}
}
// + 运算符
for(int j=0;j<str_len;++j){
if(b[j]=='+'&& false == 0){
false = 1;
if(i== opnum-1){
result=a[j-1]+a[j+1];
}
else{
int tmp = a[j-1]+a[j+1];
a[j-1]=tmp;
a[j+1]=tmp;
b[j]='#';
}
break;
}
}
// - 运算符
for(int j=0;j<str_len;++j){
if(b[j]=='-'&& false == 0){
false = 1;
if(i== opnum-1){
result=a[j-1]-a[j+1];
}
else{
int tmp = a[j-1]-a[j+1];
a[j-1]=tmp;
a[j+1]=tmp;
b[j]='#';
}
break;
}
}
}
if(opnum!=0){
return result;
}
}
int main(int argc,char *argv[]){
void error_hangling(char* message);
int serv_sock,clnt_sock;
char message[len];
int str_len,i;
int result;
struct timeval timeout; //超时结构体
fd_set reads,cpy_reads;
int fd_max,fd_num;
struct sockaddr_in serv_addr,clnt_addr;
socklen_t clnt_addr_len;
if(argc!=2){
printf("<%s>input error\n",argv[0]);
exit(1);
}
serv_sock = socket(PF_INET,SOCK_STREAM,0);
if(serv_sock==-1){
error_hangling("socket() error");
}
memset(&serv_addr,0,sizeof(serv_addr)); //sock初始化
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(atoi(argv[1]));
//绑定
if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1){
error_hangling("bind() error");
}
//监听
if(listen(serv_sock,5)==-1){
error_hangling("listen() error");
}
//文件描述符初始化,
FD_ZERO(&reads);
FD_SET(serv_sock,&reads);
fd_max = serv_sock;
//监听文件描述符
while(1){
cpy_reads = reads;
timeout.tv_sec = 5; //超时时间
timeout.tv_usec = 5000;
if((fd_num = select(fd_max+1,&cpy_reads,0,0,&timeout))==-1)
break;
if(fd_num==0)
continue;
for(i = 0;i<fd_max+1;++i){
if(FD_ISSET(i,&cpy_reads)){
if(i == serv_sock){ //connect
clnt_addr_len=sizeof(clnt_addr);
clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_len);
FD_SET(clnt_sock,&reads);
if(clnt_sock>fd_max)
fd_max=clnt_sock;
printf("the connect:%d\n",clnt_sock);
}
else{ //read message
str_len = read(i,message,BUFSIZ);
if(str_len == 0 ){ //clean
FD_CLR(i,&reads);
close(i);
printf("\nclosed client :%d ",i);
}
else{
result = calculate(message,str_len);
write(i,(char *)&result,sizeof(result));
}
}
}
}
}
close(serv_sock);
return 0;
}
客户端程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>
#define LEN 100
#define REC_RESULT 4
void error_hangling(char* message){
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
int main(int argc,char *argv[]){
int sock;
char message[LEN];
int count=0,str_len,recv_result;
struct sockaddr_in serv_addr;
if(argc!=3){
printf("input error\n");
exit(1);
}
sock = socket(PF_INET,SOCK_STREAM,0);
if(sock==-1){
error_hangling("socket() error");
}
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1){
error_hangling("connect() error");
}
else{
printf("connect...\n");
}
while(1){
fputs("input message:(q to quit)",stdout);
fgets(message,LEN,stdin);
if(!strcmp(message,"q\n"))
break;
str_len=write(sock,message,strlen(message));
read(sock,&recv_result,REC_RESULT);
printf("\nresult form serve:%d \n",recv_result);
}
close(sock);
return 0;
}