linux socket TCP 服务器向客户端传文件(任意格式)

28 篇文章 0 订阅
18 篇文章 0 订阅

Server:

 

#include<netinet/in.h> // sockaddr_in 
#include<sys/types.h>  // socket 
#include<sys/socket.h> // socket 
#include<stdio.h>    // printf 
#include<stdlib.h>   // exit 
#include<string.h>   // bzero 

#define SERVER_PORT 8000 
#define LENGTH_OF_LISTEN_QUEUE 20 
#define BUFFER_SIZE 1024 
#define FILE_NAME_MAX_SIZE 512 

int main(void)
{
	// 声明并初始化一个服务器端的socket地址结构 
	struct sockaddr_in server_addr;
	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htons(INADDR_ANY);
	server_addr.sin_port = htons(SERVER_PORT);

	// 创建socket,若成功,返回socket描述符 
	int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
	if (server_socket_fd < 0)
	{
		perror("Create Socket Failed:");
		exit(1);
	}
	int opt = 1;
	setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	// 绑定socket和socket地址结构 
	if (-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))
	{
		perror("Server Bind Failed:");
		exit(1);
	}

	// socket监听 
	if (-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))
	{
		perror("Server Listen Failed:");
		exit(1);
	}

	while (1)
	{
		// 定义客户端的socket地址结构 
		struct sockaddr_in client_addr;
		socklen_t client_addr_length = sizeof(client_addr);

		// 接受连接请求,返回一个新的socket(描述符),这个新socket用于同连接的客户端通信 
		// accept函数会把连接到的客户端信息写到client_addr中 
		int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);
		if (new_server_socket_fd < 0)
		{
			perror("Server Accept Failed:");
			break;
		}

		// recv函数接收数据到缓冲区buffer中 
		char buffer[BUFFER_SIZE];
		bzero(buffer, BUFFER_SIZE);
		if (recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
		{
			perror("Server Recieve Data Failed:");
			break;
		}

		// 然后从buffer(缓冲区)拷贝到file_name中 
		char file_name[FILE_NAME_MAX_SIZE + 1];
		bzero(file_name, FILE_NAME_MAX_SIZE + 1);
		strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));
		printf("%s\n", file_name);

		// 打开文件并读取文件数据 
		FILE *fp = fopen(file_name, "r");
		if (NULL == fp)
		{
			printf("File:%s Not Found\n", file_name);
		}
		else
		{
			bzero(buffer, BUFFER_SIZE);
			int length = 0;
			// 每读取一段数据,便将其发送给客户端,循环直到文件读完为止 
			while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
			{
				if (send(new_server_socket_fd, buffer, length, 0) < 0)
				{
					printf("Send File:%s Failed./n", file_name);
					break;
				}
				bzero(buffer, BUFFER_SIZE);
			}

			// 关闭文件 
			fclose(fp);
			printf("File:%s Transfer Successful!\n", file_name);
		}
		// 关闭与客户端的连接 
		close(new_server_socket_fd);
	}
	// 关闭监听用的socket 
	close(server_socket_fd);
	return 0;
}


Client:

 

 

#include<netinet/in.h>  // sockaddr_in 
#include<sys/types.h>  // socket 
#include<sys/socket.h>  // socket 
#include<stdio.h>    // printf 
#include<stdlib.h>    // exit 
#include<string.h>    // bzero 

#define SERVER_PORT 8000 
#define BUFFER_SIZE 1024 
#define FILE_NAME_MAX_SIZE 512 

int main()
{
	// 声明并初始化一个客户端的socket地址结构 
	struct sockaddr_in client_addr;
	bzero(&client_addr, sizeof(client_addr));
	client_addr.sin_family = AF_INET;
	client_addr.sin_addr.s_addr = htons(INADDR_ANY);
	client_addr.sin_port = htons(0);

	// 创建socket,若成功,返回socket描述符 
	int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (client_socket_fd < 0)
	{
		perror("Create Socket Failed:");
		exit(1);
	}

	// 绑定客户端的socket和客户端的socket地址结构 非必需 
	if (-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))
	{
		perror("Client Bind Failed:");
		exit(1);
	}

	// 声明一个服务器端的socket地址结构,并用服务器那边的IP地址及端口对其进行初始化,用于后面的连接 
	struct sockaddr_in server_addr;
	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) == 0)
	{
		perror("Server IP Address Error:");
		exit(1);
	}
	server_addr.sin_port = htons(SERVER_PORT);
	socklen_t server_addr_length = sizeof(server_addr);

	// 向服务器发起连接,连接成功后client_socket_fd代表了客户端和服务器的一个socket连接 
	if (connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)
	{
		perror("Can Not Connect To Server IP:");
		exit(0);
	}

	// 输入文件名 并放到缓冲区buffer中等待发送 
	char file_name[FILE_NAME_MAX_SIZE + 1];
	char file_name_save[FILE_NAME_MAX_SIZE + 1];
	bzero(file_name, FILE_NAME_MAX_SIZE + 1);
	printf("Please Input File Name On Server:\t");
	scanf("%s", file_name);

	char buffer[BUFFER_SIZE];
	bzero(buffer, BUFFER_SIZE);
	strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name));

	// 向服务器发送buffer中的数据 
	if (send(client_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
	{
		perror("Send File Name Failed:");
		exit(1);
	}

	//输入要保存的地址
	printf("Please Input File Name to Save:\t");
	scanf("%s", file_name_save);

	// 打开文件,准备写入 
	FILE *fp = fopen(file_name_save, "w");
	if (NULL == fp)
	{
		printf("File:\t%s Can Not Open To Write\n", file_name_save);
		exit(1);
	}

	// 从服务器接收数据到buffer中 
	// 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止 
	bzero(buffer, BUFFER_SIZE);
	int length = 0;
	while ((length = recv(client_socket_fd, buffer, BUFFER_SIZE, 0)) > 0)
	{
		if (fwrite(buffer, sizeof(char), length, fp) < length)
		{
			printf("File:\t%s Write Failed\n", file_name);
			break;
		}
		bzero(buffer, BUFFER_SIZE);
	}

	// 接收成功后,关闭文件,关闭socket 
	printf("Receive File:\t%s From Server IP Successful!\n", file_name);
	close(fp);
	close(client_socket_fd);
	return 0;
}

 

 

 

 

 

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
下面是一个简单的示例代码,可以在 Linux 上使用 TCP 连接向客户端发送数据: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define PORT 8080 int main() { int sockfd, new_sockfd, valread; struct sockaddr_in serv_addr, cli_addr; char buffer[1024] = {0}; char *hello = "Hello from server"; int addrlen = sizeof(serv_addr); // 创建 socket if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置地址重用 int opt = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt failed"); exit(EXIT_FAILURE); } // 设置服务器地址 serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(PORT); // 绑定 socket指定地址 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(sockfd, 3) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } // 等待客户端连接 if ((new_sockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t*)&addrlen)) < 0) { perror("accept failed"); exit(EXIT_FAILURE); } // 发送数据到客户端 send(new_sockfd, hello, strlen(hello), 0); printf("Hello message sent\n"); return 0; } ``` 这个代码会监听本地的 8080 端口,并等待客户端连接。一旦客户端连接上来,服务器就会发送一个 “Hello from server” 的消息到客户端
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值