#网络程序设计#实验二:利用TCP完成文件传输的设计和实现

更多网络程序设计的文章见:目录

实验目的

  • 输入文件路径,利用TCP实现客户文件向服务器的传输,并实现TCP的基本封装

实验原理

  • 服务器
    (1) 建立 socket
    (2) 确定服务器 scokaddr_in 结构体
    (3)点分十进制 IP 转换
    (4)使用 bind 绑定套接字
    (5)使用 listen 监听
    (6)使用 accept 接受连接请求
    (7)accept 返回新的套接字描述符
    (8)使用 recv 接收传来的数据(文件路径)
    (9)打开文件,这里需要文件名
    (10)从该字符串获取文件名
    (11)使用 recv 接收文件内容
    (12)判断 recv 函数返回的状态
    (13)将接收到的内容放入缓冲区
    (14)将缓冲区内容写入文件
    (15)关闭文件
    (16)关闭 socket
  • 客户端
    (1)建立 socket
    (2)确定服务器 scokaddr_in 结构体
    (3)点分十进制 IP 转换
    (4)使用 connect 连接
    (5)打开文件
    (6)准备缓冲区
    (7)缓冲区初始化置空
    (8)将文件内容读入缓冲区
    (9)使用 send 将缓冲区内容发送到服务器
    (10)文件内容发送完成(11)关闭文件
    (12)关闭 socket

实验内容

  • 服务器端
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
 
#define ERR_EXIT(m)				\
	do					\
	{					\
		perror(m);			\
		exit(EXIT_FAILURE);		\
	}while(0)
 
int passiveTCP()
{
	int listenfd;//创建一个套接字
	if((listenfd = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
	{
		ERR_EXIT("socket");
	}

	struct sockaddr_in servaddr;
	memset(&servaddr,0,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(5188);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);	
	
	if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
	{
		ERR_EXIT("bind");
	}
	
	if(listen(listenfd,SOMAXCONN) < 0)
		ERR_EXIT("listen");

	return listenfd;
}

int main()
{
	int fd = passiveTCP();
	char filename[100];
	char buffer[1024];

	while(1)
	{
		int conn;
		struct sockaddr_in peeraddr;
		socklen_t peerlen = sizeof(peeraddr);
		if((conn = accept(fd,(struct sockaddr*)&peeraddr,&peerlen)) < 0)
			ERR_EXIT("accept");
		else
		{
			printf("connect success\n");
			recv(conn, filename, sizeof(filename), 0);
			FILE *fp = fopen(filename, "w");
			printf("transport start\n");
			int t;
			while((t = recv(conn, buffer, 1024, 0)) > 0)
			{
				fwrite(buffer, sizeof(char), t, fp);
			}
			printf("transport finish\n");
			fclose(fp);
		}
		close(conn);
	}
	close(fd);
	return 0;
}
  • 客户端
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define ERR_EXIT(m)				\
	do					\
	{					\
		perror(m);			\
		exit(EXIT_FAILURE);		\
	}while(0)
 
int main()
{
	int sock;
	if((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
	{
		ERR_EXIT("socket");
	}
	
	struct sockaddr_in servaddr;
	memset(&servaddr,0,sizeof(servaddr));
	servaddr.sin_family = AF_INET;	
	servaddr.sin_port = htons(5188);
	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	
	char filename [100];
	char buffer[1024];

	if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
		printf("error\n");
	else
	{
		printf("success\n");
		printf("input filename:\n");
		scanf("%s", filename);
		FILE* fp = fopen(filename, "r");
		if(fp == NULL)
			printf("file not exist\n");
		else
		{
			printf("transport start\n");
			send(sock, filename, sizeof(filename), 0);
			int t;
			while((t = fread(buffer, sizeof(char), 1024, fp)) > 0)
				send(sock, buffer, t, 0);
			printf("transport finish\n");
		}
		fclose(fp);
	}

	close(sock);
	return 0;
}

实验结果

  • 传输前客户端根目录下保存着文件1.txt
    在这里插入图片描述
  • 服务器根目录下没有这个文件
    在这里插入图片描述
  • 传输开始
    在这里插入图片描述
  • 传输完成后,服务器根目录下出现1.txt,传输成功
    在这里插入图片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章