⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 Linux下网络编程
💻 C
字号:
#include <sys/socket.h>#include <netdb.h>#include <stdio.h>#include <string.h>#include <time.h>#include <malloc.h>#include <pthread.h>#define SERVER_PORT 8080 /*端口*/#define MAX_SIZE 25 /*滑动窗口的大小*/#define PACKET_SIZE 1400 /*每次读取的大小*/typedef struct packet{	int number; /*包的编号*/	int length; /*包的数据的大小*/	char buffer[PACKET_SIZE]; /*每次读取10*1024个字节*/}packet_t;typedef struct packet_control_block{	packet_t *pt;/*包的指针,每次用malloc进行产生,成功发送后释放*/	int state;/*包的状态---省略,在成功能发送就将其从Packet_State中删除即可*/	clock_t start;/*发送的起始时间,用以判断是否超时*/	int count;/*已被发送的次数,用以判断网络是否故障*/}PCB_t;typedef struct thread_parameter{	FILE *fp;	int sockfd;	struct sockaddr* addr_client;}paras_t;PCB_t Packet_State[MAX_SIZE] = {0}; /*构建一PCB控制块,包含5个元素,即滑动窗口的大小*/int Send_State = 1; /*当前文件的发送状态,是否发送完毕,以接受下一个请求*/void get_filename(char buf_filename[], char buf_request[]);void create_thread(FILE *fp, int sockfd, struct sockaddr *addr_client);void deal_request(char buf_request[], int sockfd, struct sockaddr *addr_client);void thread_send(void *ps);int main(){	int sockfd;	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)	{		printf("socket error!!!\n");		return 1;	}	struct sockaddr_in addr_server;	addr_server.sin_family = AF_INET;	addr_server.sin_port = htons(SERVER_PORT);	addr_server.sin_addr.s_addr = htonl(INADDR_ANY);	if (bind(sockfd, (struct sockaddr*)&addr_server, sizeof(struct sockaddr)) == -1)	{		printf("bind error!!!\n");		return 1;	}	struct sockaddr_in addr_client;	int addrlen = sizeof(struct sockaddr_in);	while (1)	{		char buf_request[32] = {0};		if (recvfrom(sockfd, buf_request, 32, 0, (struct sockaddr*)&addr_client, &addrlen) <= 0)		{			printf("recvfrom error!!!\n");			return 1;		}		deal_request(buf_request, sockfd, (struct sockaddr*)&addr_client);	}	return 0;}/****************************************************用于从得到的字符串取出要获得文件名***************************************************/void get_filename(char buf_filename[], char buf_request[]){	char root_directory[] = "./file_read";	char *p1 = strstr(buf_request, " ");	char *p2 = strchr(++p1, '\0');	int len = p2 - p1;	memcpy(buf_filename, root_directory, strlen(root_directory));	memcpy(buf_filename + strlen(root_directory), p1, len);}/****************************************************在满足条件下创建一个新的线程进行发送数据操作***************************************************/void create_thread(FILE *fp, int sockfd, struct sockaddr *addr_client){	pthread_t pt;	paras_t *ps = (paras_t *)malloc(sizeof(paras_t));	ps->fp = fp;	ps->sockfd = sockfd;	ps->addr_client = addr_client;	pthread_create(&pt, NULL, (void *)thread_send, (void *)ps);	pthread_detach(pt); /*分离线程*/}/****************************************************处理来自客户端的请求***************************************************/void deal_request(char buf_request[], int sockfd, struct sockaddr *addr_client){	if (!memcmp(buf_request, "GET", 3))	{		if (Send_State)/*当前能够进行文件的发送*/		{			char buf_filename[32] = {0};			get_filename(buf_filename, buf_request);			FILE *fp;			if ((fp = fopen(buf_filename, "rb")) == NULL)			{				printf("fopen error!!!\n");				return;			}			create_thread(fp, sockfd, addr_client);			create_thread(fp, sockfd, addr_client);			create_thread(fp, sockfd, addr_client);			Send_State = 0;		}	}	else	{		int i = 0;		//for (;i < MAX_SIZE;i++)		{			//if (!(Packet_State[i].pt))				//break;			int number1 = (Packet_State[i].pt)->number;			char buf[8] = {0};			memcpy(buf, buf_request + 4, 5);			int number2;			sscanf(buf, "%d", &number2);			if (number1 == number2)			{				if (!memcmp(buf_request, "ACK", 3))				{					printf("the %d block has been sended successfully!!!\n", number1);					//free(Packet_State[i].pt);					//memset(&Packet_State[i], '\0', sizeof(PCB_t));					Packet_State[i].state = 1;				}				else if (!memcmp(buf_request, "ERROR", 5))				{					Packet_State[i].count = 0;					Packet_State[i].start = 0;				}				//break;			}		}	}}/****************************************************线程函数,主要用于数据的发送***************************************************/void thread_send(void *ps){	FILE *fp = ((paras_t*)ps)->fp;	int sockfd = ((paras_t*)ps)->sockfd;	struct sockaddr addr_client = *(((paras_t*)ps)->addr_client);	free(ps); /*释放内存*/	while (1)	{		int i = 0;		int count = 0;		int state = 1; /*判断是否读到文件末尾*/		static int next_packet = 0; /*记录当前块中最大的编号*/		for (;i < MAX_SIZE;i++)		{			if (Packet_State[i].state)			{				free(Packet_State[i].pt);				Packet_State[i].pt = NULL;			}			if (!Packet_State[i].pt)			{				if (feof(fp))				{					count++;					if (count == MAX_SIZE)					{						Send_State = 1;						return;					}					continue;				}				packet_t *pt = (packet_t *)malloc(sizeof(packet_t));				pt->number = next_packet;				int len = fread(pt->buffer, 1, PACKET_SIZE, fp);				pt->length = len;				Packet_State[i].pt = pt;				Packet_State[i].count = 0;				Packet_State[i].start = 0;				Packet_State[i].state = 0;				next_packet++;			}			if (Packet_State[i].count > 10)			{				printf("net error!!!\n");				return;			}			int start = Packet_State[i].start;			if (start == 0 || time(NULL) - start > 1)			{				printf("the %d block has been sended!!!", (Packet_State[i].pt)->number);				int length = sendto(sockfd, Packet_State[i].pt, (Packet_State[i].pt)->length + 8, 0,				                    &addr_client, sizeof(struct sockaddr));				Packet_State[i].start = time(NULL);				Packet_State[i].count++;				printf("the length is %d!!!\n\n", length - 8);			}		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -