ラズベリーパイでechoサーバーを作ろう の続きです。
引き続きネットワークプログラミングです。ファイルを転送するプログラムです。
普通はftpとかfilezillaを使ってファイルを転送するわけですが、シンプルなものであればプログラミングで作れます。
前回は文字列を送受信するプログラムを作りました。
文字列をファイルに置き換えるとできます。
結局やっていることはソケットを使ってread, writeしているだけです。
ネットワークにつないでしまえば、後はどうにかなります。
サーバー側です。cpserver.c
#include <stdio.h>
cpclientと同じディレクトリにファイルを置いておきます。
あとは実行してファイル名を指定するとをサーバー側にコピーすることができます。
実行例
./cpclient
引き続きネットワークプログラミングです。ファイルを転送するプログラムです。
普通はftpとかfilezillaを使ってファイルを転送するわけですが、シンプルなものであればプログラミングで作れます。
前回は文字列を送受信するプログラムを作りました。
文字列をファイルに置き換えるとできます。
結局やっていることはソケットを使ってread, writeしているだけです。
ネットワークにつないでしまえば、後はどうにかなります。
サーバー側です。cpserver.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PORT 9877
int main(){
int i = 0;
int srcSocket;
int dstSocket;
struct sockaddr_in srcAddr;
struct sockaddr_in dstAddr;
int dstAddrSize = sizeof(dstAddr);
// 各種パラメータ
int status;
int numrcv;
char buf[1024];
int len = 0;
int size = 0;
char filename[64];
int fp;
unsigned long filesize = 0;
unsigned long totalrcv = 0;
// sockaddr_in 構造体のセット
bzero((char *)&srcAddr, sizeof(srcAddr));
srcAddr.sin_port = htons(PORT);
srcAddr.sin_family = AF_INET;
srcAddr.sin_addr.s_addr = INADDR_ANY;
srcSocket = socket(AF_INET, SOCK_STREAM, 0);
bind(srcSocket, (struct sockaddr *)&srcAddr, sizeof(srcAddr));
listen(srcSocket, 1);
// 接続の受付け
printf("接続を待っています\nクライアントプログラムを動かして下さい\n");
dstSocket = accept(srcSocket, (struct sockaddr *)&dstAddr, &dstAddrSize);
printf("%s から接続を受けました\n",inet_ntoa(dstAddr.sin_addr));
while(1) {
memset(filename, 0, sizeof(filename));
len = read(dstSocket, buf, 2);
if(len < 0) {
printf("エラー: ファイル名のエラーです。\n");
return -1;
}
size = buf[0] << 8;
size |= buf[1];
len = read(dstSocket, buf, 4);
if(len < 0) {
printf("エラー: ファイルサイズのエラーです。\n");
return -1;
}
filesize = buf[0] << 24;
filesize |= buf[1] << 16;
filesize |= buf[2] << 8;
filesize |= buf[3];
printf("filesize = %ld byte\n", filesize);
len = read(dstSocket, filename, size);
if (len < 0) {
printf("エラー: ファイル名を取得できませんでした。");
return -1;
} else if (!strcmp(filename, "quit")) {
printf("プログラムを終了します。\n\n");
return 0;
}
printf("filename = %s\n", filename);
/* 書き込みファイルを開く */
if ((fp = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
printf("エラー ファイルを作成できません");
return -1;
}
totalrcv = 0;
while(1){
//パケットの受信
numrcv = read(dstSocket, buf, 1024);
//printf("%d %d\n", i, numrcv);
if(numrcv <= 0 ){
break;
}
write(fp, buf, numrcv);
totalrcv += numrcv;
if(totalrcv >= filesize) {
printf("%s 転送完了\n\n", filename);
break;
}
}
close(fp);
}
close(srcSocket);
return(0);
}
クライアント側です。 cpclient.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 9877 //サーバープログラムとポート番号を合わせてください
char buf[1024];
char filesize[4];
int main(){
char destination[32] = "192.168.0.10";//サーバーのIPアドレスを入れて下さい。
//ソケット,sockaddr_in 構造体
int dstSocket;
struct sockaddr_in dstAddr;
struct hostent *hp;
int numrcv;
char filename[100];
int len = 0;
int fp;
int size;
struct stat statBuf;
//sockaddr_in 構造体のセット
bzero((char *)&dstAddr, sizeof(dstAddr));
dstAddr.sin_family = AF_INET;
dstAddr.sin_port = htons(PORT);
hp = gethostbyname(destination);
bcopy(hp->h_addr, &dstAddr.sin_addr, hp->h_length);
//ソケットの生成
dstSocket = socket(AF_INET, SOCK_STREAM, 0);
//接続
if (connect(dstSocket, (struct sockaddr *)&dstAddr, sizeof(dstAddr)) < 0){
printf("%s に接続できませんでした\n",destination);
return(-1);
}
printf("%s に接続しました\n",destination);
while(1) {
len = 0;
memset(filename, 0, sizeof(filename));
printf("送信するファイル名を入力してください\n");
printf("quitで終了します\n\n");
scanf("%s",filename);
if (!strcmp(filename, "quit")) {
printf("->bye\n");
write(dstSocket, "00quit", 6);
close(dstSocket);
break;
}
while(filename[len] != '\0') {
len++;
}
len++;
buf[0] = (len >> 8) & 0xFF;
buf[1] = len & 0xFF;
fp = open(filename, O_RDONLY);
if (fp < 0) {
printf("エラー: ファイルを開けません\n");
return(-1);
}
fstat(fp, &statBuf);
printf("filesize = %ld byte\n", statBuf.st_size);
filesize[0] = (statBuf.st_size >> 24 ) & 0xFF;
filesize[1] = (statBuf.st_size >> 16 ) & 0xFF;
filesize[2] = (statBuf.st_size >> 8) & 0xFF;
filesize[3] = statBuf.st_size & 0xFF;
write(dstSocket, buf, 2);
write(dstSocket, filesize, 4);
write(dstSocket,filename, len);
while (1){
/* ファイルから読み込み */
size = read (fp, buf, sizeof(buf));
/* データが無ければループを抜ける */
if (size <= 0) {
break;
}
//パケットの送信
write(dstSocket, buf, size);
}
write(dstSocket,"filetransferred", sizeof("filetransferred"));
printf("%s 転送完了しました\n\n",filename);
close(fp);
}
close(dstSocket);
return(0);
}
cpclientと同じディレクトリにファイルを置いておきます。
あとは実行してファイル名を指定するとをサーバー側にコピーすることができます。
実行例
./cpclient
送信するファイル名を入力してください
quitで終了します
crazy.mp3
filesize = 6211191 byte
crazy.mp3 転送完了しました