溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何實現(xiàn)linux下socket文件傳輸

發(fā)布時間:2022-01-25 10:27:18 來源:億速云 閱讀:161 作者:kk 欄目:開發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)如何實現(xiàn)linux下socket文件傳輸,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

什么是 socket?

socket 的原意是“插座”,在計算機通信領(lǐng)域,socket 被翻譯為“套接字”,它是計算機之間進(jìn)行通信的一種約定或一種方式。通過 socket 這種約定,一臺計算機可以接收其他計算機的數(shù)據(jù),也可以向其他計算機發(fā)送數(shù)據(jù)。

我們把插頭插到插座上就能從電網(wǎng)獲得電力供應(yīng),同樣,為了與遠(yuǎn)程計算機進(jìn)行數(shù)據(jù)傳輸,需要連接到因特網(wǎng),而 socket 就是用來連接到因特網(wǎng)的工具。

socket 的典型應(yīng)用就是 Web 服務(wù)器和瀏覽器:瀏覽器獲取用戶輸入的 URL,向服務(wù)器發(fā)起請求,服務(wù)器分析接收到的 URL,將對應(yīng)的網(wǎng)頁內(nèi)容返回給瀏覽器,瀏覽器再經(jīng)過解析和渲染,就將文字、圖片、視頻等元素呈現(xiàn)給用戶。

學(xué)習(xí) socket,也就是學(xué)習(xí)計算機之間如何通信,并編寫出實用的程序。

UNIX/Linux 中的 socket 是什么?

在 UNIX/Linux 系統(tǒng)中,為了統(tǒng)一對各種硬件的操作,簡化接口,不同的硬件設(shè)備也都被看成一個文件。對這些文件的操作,等同于對磁盤上普通文件的操作。

你也許聽很多高手說過,UNIX/Linux 中的一切都是文件!那個家伙說的沒錯。

為了表示和區(qū)分已經(jīng)打開的文件,UNIX/Linux 會給每個文件分配一個 ID,這個 ID 就是一個整數(shù),被稱為文件描述符(File Descriptor)。例如:

  • 通常用 0 來表示標(biāo)準(zhǔn)輸入文件(stdin),它對應(yīng)的硬件設(shè)備就是鍵盤;

  • 通常用 1 來表示標(biāo)準(zhǔn)輸出文件(stdout),它對應(yīng)的硬件設(shè)備就是顯示器。

UNIX/Linux 程序在執(zhí)行任何形式的 I/O 操作時,都是在讀取或者寫入一個文件描述符。一個文件描述符只是一個和打開的文件相關(guān)聯(lián)的整數(shù),它的背后可能是一個硬盤上的普通文件、FIFO、管道、終端、鍵盤、顯示器,甚至是一個網(wǎng)絡(luò)連接。

linux下socket文件傳輸方法:

本文所述示例程序是基于Linux平臺的socket網(wǎng)絡(luò)編程,實現(xiàn)文件傳輸功能。該示例是基于TCP流協(xié)議實現(xiàn)的socket網(wǎng)絡(luò)文件傳輸程序。采用C語言編寫。最終能夠?qū)崿F(xiàn)傳輸任何格式文件的文件傳輸程序。

具體實現(xiàn)代碼如下:
Server端代碼如下:
[cpp] view plain copy
/*************************************************************************
> File Name: Server.c
> Author: SongLee
************************************************************************/

#include// sockaddr_in
#include // socket
#include// socket
#include   // printf
#include  // exit
#include  // bzero

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

int main(void)
{
// 聲明并初始化一個服務(wù)器端的socket地址結(jié)構(gòu)
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);

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

// 綁定socket和socket地址結(jié)構(gòu)
if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))
{
perror(“Server Bind Failed:”);
exit(1);
}

// socket監(jiān)聽
if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))
{
perror(“Server Listen Failed:”);
exit(1);
}

while(1)
{
// 定義客戶端的socket地址結(jié)構(gòu)
struct sockaddr_in client_addr;
socklen_t client_addr_length = sizeof(client_addr);

// 接受連接請求,返回一個新的socket(描述符),這個新socket用于同連接的客戶端通信
// accept函數(shù)會把連接到的客戶端信息寫到client_addr中
int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);
if(new_server_socket_fd {
perror(“Server Accept Failed:”);
break;
}

// recv函數(shù)接收數(shù)據(jù)到緩沖區(qū)buffer中
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) {
perror(“Server Recieve Data Failed:”);
break;
}

// 然后從buffer(緩沖區(qū))拷貝到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);

// 打開文件并讀取文件數(shù)據(jù)
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;
// 每讀取一段數(shù)據(jù),便將其發(fā)送給客戶端,循環(huán)直到文件讀完為止
while((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
{
if(send(new_server_socket_fd, buffer, length, 0) {
printf(“Send File:%s Failed./n”, file_name);
break;
}
bzero(buffer, BUFFER_SIZE);
}

// 關(guān)閉文件
fclose(fp);
printf(“File:%s Transfer Successful!\n”, file_name);
}
// 關(guān)閉與客戶端的連接
close(new_server_socket_fd);
}
// 關(guān)閉監(jiān)聽用的socket
close(server_socket_fd);
return 0;
}
Client端代碼如下:
[cpp] view plain copy
/*************************************************************************
> File Name: Client.c
> Author: SongLee
************************************************************************/

#include // sockaddr_in
#include // socket
#include // socket
#include   // printf
#include   // exit
#include   // bzero

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

int main()
{
// 聲明并初始化一個客戶端的socket地址結(jié)構(gòu)
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);

// 創(chuàng)建socket,若成功,返回socket描述符
int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(client_socket_fd {
perror(“Create Socket Failed:”);
exit(1);
}

// 綁定客戶端的socket和客戶端的socket地址結(jié)構(gòu) 非必需
if(-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))
{
perror(“Client Bind Failed:”);
exit(1);
}

// 聲明一個服務(wù)器端的socket地址結(jié)構(gòu),并用服務(wù)器那邊的IP地址及端口對其進(jìn)行初始化,用于后面的連接
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);

// 向服務(wù)器發(fā)起連接,連接成功后client_socket_fd代表了客戶端和服務(wù)器的一個socket連接
if(connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) {
perror(“Can Not Connect To Server IP:”);
exit(0);
}

// 輸入文件名 并放到緩沖區(qū)buffer中等待發(fā)送
char file_name[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));

// 向服務(wù)器發(fā)送buffer中的數(shù)據(jù)
if(send(client_socket_fd, buffer, BUFFER_SIZE, 0) {
perror(“Send File Name Failed:”);
exit(1);
}

// 打開文件,準(zhǔn)備寫入
FILE *fp = fopen(file_name, “w”);
if(NULL == fp)
{
printf(“File:\t%s Can Not Open To Write\n”, file_name);
exit(1);
}

// 從服務(wù)器接收數(shù)據(jù)到buffer中
// 每接收一段數(shù)據(jù),便將其寫入文件中,循環(huán)直到文件接收完并寫完為止
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) {
printf(“File:\t%s Write Failed\n”, file_name);
break;
}
bzero(buffer, BUFFER_SIZE);
}

// 接收成功后,關(guān)閉文件,關(guān)閉socket
printf(“Receive File:\t%s From Server IP Successful!\n”, file_name);
close(fp);
close(client_socket_fd);
return 0;
}

什么是Linux系統(tǒng)

Linux是一種免費使用和自由傳播的類UNIX操作系統(tǒng),是一個基于POSIX的多用戶、多任務(wù)、支持多線程和多CPU的操作系統(tǒng),使用Linux能運行主要的Unix工具軟件、應(yīng)用程序和網(wǎng)絡(luò)協(xié)議。

上述就是小編為大家分享的如何實現(xiàn)linux下socket文件傳輸了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI