計算服務器架構模式與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);

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章