计算服务器架构模式与UDP CS模式

在这里插入图片描述
一、±*操作服务器

  1. 客户端连接到服务器端后,以1字节整数形式传递等待计算数学个数: 客户端向服务器传递的每个整数型数据占用4个字节;

  2. 传递整数型数据后接着传递运算符,运算符信息占用1字节: 选择字符+一*传递; 服务器端以4个字节整数型向客户端传回运算符结果:

  3. 客户端得到运算结果后终止与服务器的连接:

在这里插入图片描述
op_server.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>



#define BUF_SIZE 1024

#define OPSZ 4

void error_handling(char *message);

int calculate(int opnum, int opnds[], char oprator);



int main(int argc, char *argv[])

{

	int serv_sock, clnt_sock;

	char opinfo[BUF_SIZE];

	int result, opnd_cnt, i;

	int recv_cnt, recv_len;	

	struct sockaddr_in serv_adr, clnt_adr;

	socklen_t clnt_adr_sz;

	if(argc!=2) {

		printf("Usage : %s <port>\n", argv[0]);

		exit(1);

	}

	

	serv_sock=socket(PF_INET, SOCK_STREAM, 0);   

	if(serv_sock==-1)

		error_handling("socket() error");

	

	memset(&serv_adr, 0, sizeof(serv_adr));

	serv_adr.sin_family=AF_INET;

	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);

	serv_adr.sin_port=htons(atoi(argv[1]));



	if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)

		error_handling("bind() error");

	if(listen(serv_sock, 5)==-1)

		error_handling("listen() error");	

	clnt_adr_sz=sizeof(clnt_adr);



	for(i=0; i<5; i++)

	{

		opnd_cnt=0;

		clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);	

		read(clnt_sock, &opnd_cnt, 1);

		

		recv_len=0;

		while((opnd_cnt*OPSZ+1)>recv_len)

		{

			recv_cnt=read(clnt_sock, &opinfo[recv_len], BUF_SIZE-1);

			recv_len+=recv_cnt;

		}

		result=calculate(opnd_cnt, (int*)opinfo, opinfo[recv_len-1]);

		write(clnt_sock, (char*)&result, sizeof(result));

		close(clnt_sock);

	}

	close(serv_sock);

	return 0;

}



int calculate(int opnum, int opnds[], char op)

{

	int result=opnds[0], i;

	

	switch(op)

	{

	case '+':

		for(i=1; i<opnum; i++) result+=opnds[i];

		break;

	case '-':

		for(i=1; i<opnum; i++) result-=opnds[i];

		break;

	case '*':

		for(i=1; i<opnum; i++) result*=opnds[i];

		break;

	}

	return result;

}



void error_handling(char *message)

{

	fputs(message, stderr);

	fputc('\n', stderr);

	exit(1);

}

op_client.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>



#define BUF_SIZE 1024

#define RLT_SIZE 4

#define OPSZ 4

void error_handling(char *message);



int main(int argc, char *argv[])

{

	int sock;

	char opmsg[BUF_SIZE];

	int result, opnd_cnt, i;

	struct sockaddr_in serv_adr;

	if(argc!=3) {

		printf("Usage : %s <IP> <port>\n", argv[0]);

		exit(1);

	}

	

	sock=socket(PF_INET, SOCK_STREAM, 0);   

	if(sock==-1)

		error_handling("socket() error");

	

	memset(&serv_adr, 0, sizeof(serv_adr));

	serv_adr.sin_family=AF_INET;

	serv_adr.sin_addr.s_addr=inet_addr(argv[1]);

	serv_adr.sin_port=htons(atoi(argv[2]));

	

	if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)

		error_handling("connect() error!");

	else

		puts("Connected...........");



	fputs("Operand count: ", stdout);

	scanf("%d", &opnd_cnt);

	opmsg[0]=(char)opnd_cnt;

	

	for(i=0; i<opnd_cnt; i++)

	{

		printf("Operand %d: ", i+1);

		scanf("%d", (int*)&opmsg[i*OPSZ+1]);

	}

	fgetc(stdin);

	fputs("Operator: ", stdout);

	scanf("%c", &opmsg[opnd_cnt*OPSZ+1]);

	write(sock, opmsg, opnd_cnt*OPSZ+2);

	read(sock, &result, RLT_SIZE);

	

	printf("Operation result: %d \n", result);

	close(sock);

	return 0;

}



void error_handling(char *message)

{

	fputs(message, stderr);

	fputc('\n', stderr);

	exit(1);

}

二、UDP回声

UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。

UDP协议基本上是IP协议与上层协议的接口。UDP协议适用端口分别运行在同一台设备上的多个应用程序。

UDP提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,

UDP传输的可靠性由应用层负责。常用的UDP端凵号有53(DNS)、69(TFTP)、161(SNMP)使用UDP协议包括:TFTP、SNMP、NFS、DNS、BOOTP。

UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如DNS、TFTP、SNMP等。

UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。UDP信息包的标题很短,只有8个字节,相对TCP的20个字节信息包而言UDP的额外开销很小。吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。
虽然UDP是一个不可靠的协议,但它是分发信息的一个理想协议。例如,在屏幕上报告股票市场、显示航空信息等等。UDP也用在路由信息协RIP(RoutingInformationProtocol)中修改路由表。在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。UDP广泛用在多媒体应用中。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

uecho_server.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>



#define BUF_SIZE 30

void error_handling(char *message);



int main(int argc, char *argv[])

{

	int serv_sock;

	char message[BUF_SIZE];

	int str_len;

	socklen_t clnt_adr_sz;

	

	struct sockaddr_in serv_adr, clnt_adr;

	if(argc!=2){

		printf("Usage : %s <port>\n", argv[0]);

		exit(1);

	}

	

	serv_sock=socket(PF_INET, SOCK_DGRAM, 0);

	if(serv_sock==-1)

		error_handling("UDP socket creation error");

	

	memset(&serv_adr, 0, sizeof(serv_adr));

	serv_adr.sin_family=AF_INET;

	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);

	serv_adr.sin_port=htons(atoi(argv[1]));

	

	if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)

		error_handling("bind() error");



	while(1) 

	{

		clnt_adr_sz=sizeof(clnt_adr);

		str_len=recvfrom(serv_sock, message, BUF_SIZE, 0, 

								(struct sockaddr*)&clnt_adr, &clnt_adr_sz);

		sendto(serv_sock, message, str_len, 0, 

								(struct sockaddr*)&clnt_adr, clnt_adr_sz);

	}	

	close(serv_sock);

	return 0;

}



void error_handling(char *message)

{

	fputs(message, stderr);

	fputc('\n', stderr);

	exit(1);

}

uecho_client.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>



#define BUF_SIZE 30

void error_handling(char *message);



int main(int argc, char *argv[])

{

	int sock;

	char message[BUF_SIZE];

	int str_len;

	socklen_t adr_sz;

	

	struct sockaddr_in serv_adr, from_adr;

	if(argc!=3){

		printf("Usage : %s <IP> <port>\n", argv[0]);

		exit(1);

	}

	

	sock=socket(PF_INET, SOCK_DGRAM, 0);   

	if(sock==-1)

		error_handling("socket() error");

	

	memset(&serv_adr, 0, sizeof(serv_adr));

	serv_adr.sin_family=AF_INET;

	serv_adr.sin_addr.s_addr=inet_addr(argv[1]);

	serv_adr.sin_port=htons(atoi(argv[2]));

	

	while(1)

	{

		fputs("Insert message(q to quit): ", stdout);

		fgets(message, sizeof(message), stdin);     

		if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))	

			break;

		

		sendto(sock, message, strlen(message), 0, 

					(struct sockaddr*)&serv_adr, sizeof(serv_adr));

		adr_sz=sizeof(from_adr);

		str_len=recvfrom(sock, message, BUF_SIZE, 0, 

					(struct sockaddr*)&from_adr, &adr_sz);



		message[str_len]=0;

		printf("Message from server: %s", message);

	}	

	close(sock);

	return 0;

}



void error_handling(char *message)

{

	fputs(message, stderr);

	fputc('\n', stderr);

	exit(1);

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值