C/S模型 多线程服务器实现简单计算工作并回馈客户端

本位代码实现客户端输入相应需要计算的表达式,服务器做简单计算,并将结果返回。

头文件:

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define INIT_THREAD_NUM 5
#define MAXLINE 1024
#define err_quit(m) \
		do{ \
			perror(m); \
			exit(1); \
		}while(0)

typedef enum{IDLE, BUSY}WORK_STATE;
typedef enum{ADD, SUB, MUL, DIV, MOD}OPER_ENUM;
typedef struct {
	int       op1;
	int       op2;
	OPER_ENUM oper;
}oper_struct;

服务器代码:

#include "../utili.h"

void math_operation(oper_struct *ptr, int *res);
static void *th_fn(void *arg);

int main()
{
	int listenfd;
	struct sockaddr_in servaddr;

	if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		err_quit("socket err.\n");
	
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(6666);
	servaddr.sin_addr.s_addr = INADDR_ANY;

	int on = 1;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

	if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
		err_quit("bind err.\n");
	
	if(listen(listenfd, SOMAXCONN) < 0)
		err_quit("listen err.\n");
	
	int *ptr_connfd;
	struct sockaddr_in clientaddr;
	socklen_t len = sizeof(clientaddr);
	pthread_t tid;

	for(; ;){
		ptr_connfd = (int *)malloc(sizeof(int));
		if( (*ptr_connfd = accept(listenfd, (struct sockaddr*)&clientaddr, &len)) < 0)
			err_quit("accept err.\n");
		else
			printf("client: IP:%s PORT:%d connect.\n", inet_ntoa(clientaddr.sin_addr),
													ntohs(clientaddr.sin_port));
		
		if(pthread_create(&tid, NULL, th_fn, ptr_connfd) != 0)
			err_quit("create pthread err.\n");
	}
	return 0;
}

void math_operation(oper_struct *ptr, int *res)
{
	switch(ptr->oper){
		case ADD:
			*res = ptr->op1 + ptr->op2;
			break;
		case SUB:
			*res = ptr->op1 - ptr->op2;
			break;
		case MUL:
			*res = ptr->op1 * ptr->op2;
			break;
		case DIV:
			*res = ptr->op1 / ptr->op2;
			break;
		case MOD:
			*res = ptr->op1 % ptr->op2;
			break;
		default: 
			break;
	}
}

static void *th_fn(void *arg)
{
	pthread_detach(pthread_self());
	int connfd = *(int *)arg;
	free(arg);

	int res;
	oper_struct ops; 
	for(; ;){
		recv(connfd, &ops, sizeof(ops), 0);
		math_operation(&ops, &res);
		printf("the result is:%d\n", res);
		send(connfd, &res, sizeof(res), 0);
	}
	close(connfd);
	return (void *)0;
}

客户端代码:

#include "../utili.h"

void input_opernum(oper_struct *pointer);

int main()
{
	int sockfd;
	struct sockaddr_in servaddr;

	if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		err_quit("socket err.\n");
	
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(6666);
	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

	if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
		err_quit("connect err.\n");
	
	oper_struct ops;
	char *symbol;
	char recvbuff[MAXLINE];
	for( ; ;){
		printf("please input operator symbol:>\n");
		scanf("%s", symbol);
		if(strncmp(symbol, "add", 3) == 0){
			ops.oper = ADD;
			input_opernum(&ops);
		}
		else if(strncmp(symbol, "sub", 3) == 0){
			ops.oper = SUB;
			input_opernum(&ops);
		}
		else if(strncmp(symbol, "mul", 3) == 0){
			ops.oper = MUL;
			input_opernum(&ops);
		}
		else if(strncmp(symbol, "div", 3) == 0){
			ops.oper = DIV;
			input_opernum(&ops);
		}
		else if(strncmp(symbol, "mod", 3) == 0){
			ops.oper = MOD;
			input_opernum(&ops);
		}
		else{
			printf("invilid input.\n");
			continue;
		}
		
		send(sockfd, &ops, sizeof(ops), 0);

		recv(sockfd, recvbuff, sizeof(int), 0);
		printf("the answer is:>%d\n", *(int*)recvbuff);
	}
	close(sockfd);

	return 0;
}

void input_opernum(oper_struct *pointer)
{
	printf("please input operation num:>\n");
	scanf("%d %d", &(pointer->op1), &(pointer->op2));
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值