calc.h
#include
#include
#include
#include
#include
typedef enum {QUIT, ADD, SUB, MUL, DIV, MODE}ENUM_CAL_TYPE; //
#define CMD_SIZE 5
typedef struct calcst
{
int op1; //操作数1
int op2; //操作数2
ENUM_CAL_TYPE op; //操作(+,-,*,/...)
}calcst;
socket.h (封装)
#define TCP 0
#define UDP 1
#define LISTEN_QUEUE_SIZE 5
int start_up(char *ip, short port, int mode)
{
int sockfd;
if(mode == TCP)
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
}
else if(mode == UDP)
{
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
}
else
{
printf("mode error,mode must be TCP or UDP!\n ");
return -1;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = inet_addr(ip);
socklen_t len = sizeof(struct sockaddr);
int yes = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); //地址重用
int ret = bind(sockfd, (struct sockaddr*)&address, len);
if(ret == -1)
{
perror("bind");
return -1;
}
if(mode == TCP)
{
ret = listen(sockfd, LISTEN_QUEUE_SIZE);
if(ret == -1)
{
perror("listen");
return -1;
}
}
return sockfd;
}
ser.c
#include"socket.h"
#include"calc.h"
int main(int argc, char *argv[])
{
void process_hander(int sockConn);
int sockSer = start_up(argv[1], atoi(argv[2]), TCP);
if(sockSer == -1)
{
perror("socket error\n");
return -1;
}
printf("Server waiting connect\n");
struct sockaddr_in addrCli;
socklen_t len = sizeof(struct sockaddr);
int sockConn;
while(1)
{
sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &len);
if(sockConn == -1)
{
perror("Client connect fail\n");
return -1;
}
else
{
printf("<=========Client=============>\n"); //打印客户端信息 IP port
printf("< ip = %s>\n", inet_ntoa(addrCli.sin_addr));
printf("< port = %d>\n", ntohs(addrCli.sin_port));
}
pid_t pid = fork();
if(pid == 0)
{
process_hander(sockConn); //子进程 --交给处理函数
}
else if(pid > 0)
{
close(sockConn);
}
else
{
perror("fork");
}
}
close(sockSer);
return 0;
}
void process_hander(int sockConn)
{
calcst oper;
int ret;
int result;
while(1)
{
ret = recv(sockConn, &oper, sizeof(oper), 0);
if(ret < 0)
{
perror("receve error");
continue;
}
if(oper.op == ADD)
result = oper.op1 + oper.op2;
else if(oper.op == SUB)
result = oper.op1 - oper.op2;
else if(oper.op == MUL)
result = oper.op1 * oper.op2;
else if(oper.op == DIV)
result = oper.op1 / oper.op2;
else if(oper.op == MODE)
result = oper.op1 % oper.op2;
else if(oper.op == QUIT)
{
printf("Client Quit.\n");
break;
}
ret = send(sockConn, &result, sizeof(result), 0); //将计算结果发给客户端
if(result < 0)
{
perror("send error");
continue;
}
}
close(sockConn);
}
cli.c
:
#include"calc.h"
int main(int argc, char *argv[])
{
int sockCli = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addrSer;
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(atoi(argv[2]));
addrSer.sin_addr.s_addr = inet_addr(argv[1]);
socklen_t len = sizeof(struct sockaddr);
int ret = connect(sockCli, (struct sockaddr*)&addrSer, len);
if(ret == -1)
{
perror("connect error\n");
close(sockCli);
return -1;
}
else
printf("connect server success\n");
calcst oper;
char cmd[CMD_SIZE];
int result;
while(1)
{
printf("Please input cmd\n");
scanf("%s", cmd);
printf("Please input op1 and op2\n");
scanf("%d %d", &oper.op1, &oper.op2);
if(strcmp(cmd, "add") == 0)
oper.op = ADD;
else if(strcmp(cmd, "sub") == 0)
oper.op = SUB;
else if(strcmp(cmd, "mul") == 0)
oper.op = MUL;
else if(strcmp(cmd, "div") == 0)
oper.op = DIV;
else if(strcmp(cmd, "mode") == 0)
oper.op = MODE;
else if(strcmp(cmd,"quit") == 0)
break;
ret = send(sockCli, &oper, sizeof(oper), 0); //客户端将要计算的数据和操作发给服务器
if(ret < 0)
{
perror("send data error");
continue;
}
ret = recv(sockCli, &result, sizeof(result), 0); //接受来自服务器的计算结果
if(ret < 0)
{
perror("receve error");
continue;
}
printf("result = %d\n", result);
}
close(sockCli);
printf("System Quiting...");
}
运行效果:
当然这里有点小问题,就是客户怎么知道你的cmd 该输入啥, 其实可以打印一个菜单来解决...说白了,这是一个只有你自己才能使用的小型计算器...haha