webサーバにファイルをPOSTする方法。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
helloworld1853
記事: 181
登録日時: 12年前

webサーバにファイルをPOSTする方法。

#1

投稿記事 by helloworld1853 » 12年前

webサーバのpost.cgiにファイルをpostする方法を知りたいです。

自分なりにソースコードを書いてみましたが

100000バイトまでしか送れません。

ソースコードを以下に掲載します。

コード:

#include <stdio.h>
#include <winsock2.h>

int main( void )
{
	int sock, ret;
	struct sockaddr_in addr;
	FILE *fp;
	char *fname = "test.bmp";
	unsigned char buf[100000];
	//char buf1[1000000];
	char body[100000];
	int  i;
	int size;
	//int counter;

	WSADATA wsadata;
	WSAStartup( 0x0101, &wsadata );
	fp = fopen( fname, "rb" );
	size = fread( buf, sizeof( unsigned char ), 100000, fp );
	printf("size is%d\n",size);
	for( i=0; i<size; i++ )
	{
		
		printf( "%02X ", buf[i] );
	}
	puts("");
	//PROC pfn0rig;
	//printf("%d\n",buf[5]);
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("61.214.105.140");
	addr.sin_port = htons(80);
	
	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) 
	{
		printf( "can't open http port\n" );
		return 0;
	}
	strcpy(body,"namae=");
	memcpy(&body[6],buf,size);
	memcpy(&body[6+size],"\r\n",2);
	//sprintf(body,"namae=%s\r\n",buf);
	body[size+6]='\0';
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
	char length[100];
	sprintf( length, "Content-Length: %d\r\n", 6+size );
	int n=0;
	send(sock,head,strlen(head),0);
	send(sock,length,strlen(length),0);
	send(sock,"\r\n",2,0);
	send(sock,body,size,0);
	
	closesocket( sock );
	fclose( fp );

}

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#2

投稿記事 by h2so5 » 12年前

helloworld1853 さんが書きました: 自分なりにソースコードを書いてみましたが

100000バイトまでしか送れません。
freadの引数でそのように指定しているのだから当たり前では?

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#3

投稿記事 by helloworld1853 » 12年前

いいそびれました。

最低でも1MB送信したいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#4

投稿記事 by softya(ソフト屋) » 12年前

freadしてsendを繰り返すだけですよ。
http://dixq.net/forum/viewtopic.php?t=10533
前の質問にも書かれてますが、バイナリファイルを含めたファイルの扱いをちゃんと勉強して方が良いのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#5

投稿記事 by helloworld1853 » 12年前

>freadしてsendを繰り返すだけですよ。

POST /~yamada_mama_papa/test.cgi HTTP/1.0
Host: s1.muryo.etowns.net
Content-Length:1000000

namae=省略
namae=省略

 ・
namae=省略

というデータが送られるようにすればいいと

言う意味でしょうか。

ご意見をお聞かせください。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#6

投稿記事 by softya(ソフト屋) » 12年前

namae=省略
の省略部分で1MBって訳では無いのですか?
どういう風に送りたいのか良く分かりません。
1つの情報なら
namae=省略
は1つで良いはずですよね。

【追記】
送るデータの
Content-Type:
も必要では無いでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#7

投稿記事 by ISLe » 12年前

そもそも画像ファイルの中身を送信するのに
namae=~\r\n
なんてする必要なくて

だけを送信すればいいんですよね。

たぶん「GETと同じことをPOSTでするには」という感じの解説を読んで誤解したのでしょう。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#8

投稿記事 by helloworld1853 » 12年前

>freadしてsendを繰り返すだけですよ。

これをどうやら僕が誤って理解してしまったようです。

これは一体どう言う意味でしょうか。

お手柔らかにお願いします。

あとISLe さんありがとうございます。

そうだったんですか。

しかし、namaeだけでなくnamae1,namae2にもpostしたい場合は

僕のやり方でもアリでしょうか。

よろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#9

投稿記事 by softya(ソフト屋) » 12年前

cgiの方でどうやって受け取るつもりなんでしょうか?
考えているPOSTするデータの形式を説明して下さい。
bmpファイルのバイナリデータだけじゃないんですか?ファイル名とかも送る?
でもnamae1とnamae2って何が入るのでしょうか?

freadに関しては、100バイトのバッファでtest.bmpをfwriteで別ファイルにコピーする方法がわかりますか?
勉強の為、プログラムを組んでみてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#10

投稿記事 by ISLe » 12年前

helloworld1853 さんが書きました:しかし、namaeだけでなくnamae1,namae2にもpostしたい場合は
CGI.pmでパラメータとして受け取りたいなら、バイナリデータをそのまま送ってはダメですよ。
URLエンコードしてテキストデータに変換する必要があります。

画像のバイナリデータをそのまま送る方法にすれば送信も受信もシンプルになりますけど。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#11

投稿記事 by helloworld1853 » 12年前

コード:

#!/usr/local/bin/perl
use CGI;
$q = new CGI;
$Name = $q->param('namae');#1~100000
print "Content-type: text/html\n\n";
print "<META http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n";
print $Name;
open (OUT,"> test.bmp");
print OUT $Name;
close (OUT);
print 'sucess';
exit;
post.cgiのソースコードです。

ここにはnamae1,namae2がありませんけど

当初 namaeに100KB分をnamae1に100KB分を・・・・

と分けて送信し、

cgiの方でnamae,namae1,namae2を結合することにより

1MBの画像ファイルを生成しようとしたのですが、

無理だったので取り消しました。

ちなみにこのプログラムは動作しました。

ファイルをコピーするプログラムも書いてみました。

動作未確認ですけど動く自信があります。

コード:

#include <stdio.h>
int main(void)
{
  FILE *fpread;
  FILE *fpwrite;
  char *fnameREAD = "test.bmp";
  char *fnameWRITE= "test1.bmp";
  unsigned char buf[100];
  int i, size;

  fpread = fopen( fnameREAD, "rb" );
  if( fpread == NULL )
  {
    return -1;
  }

  fpwrite = fopen( fnameWRITE, "wb" );
  if( fpwrite == NULL )
  {
    return -1;
  }

  size = fread( buf, sizeof( unsigned char ), 10000, fpread );
  fwrite( buf, sizeof( unsigned char ), size, fpwrite );

  fclose( fpread );
  fclose( fpwrite );

  return 0;
}

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#12

投稿記事 by beatle » 12年前

動く自信があるのはいいのですが、動作確認くらいしませんか?
ぱっとみ、bufが100バイト分しか確保されていないのに、そこへ10000バイトもの巨大データをfreadしようとしているようですが。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#13

投稿記事 by softya(ソフト屋) » 12年前

ファイルコピーですがbeatleさんの言われる点も含め不特定サイズのファイルを扱える処理にはなっていません。ループ処理が必要です。
必ずテストしてくださいね。コレが分かれば、バッファサイズ以上の不特定サイズをsendする方法も理解できますよ。

CGIに関しては、 Content-type: multipart/form-dataを前提としている書き方ですね。
「ファイルをアップロードさせる」
http://www.ksknet.net/perl/post_26.html

なので、送信側はこちらを参考にフォーマットを組み立てる必要があります。
「[Studying HTTP] HTTP Message Body」
http://www.studyinghttp.net/body#Form-data
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#14

投稿記事 by ISLe » 12年前

helloworld1853 さんが書きました:ちなみにこのプログラムは動作しました。
例えば画像データの中に'&'と同じ文字コードのバイトデータが含まれているとそこで切れてしまう気がします。


CGI.pmを使っているのでmultipart/form-dataかどうかは関係ないと思いますが、そもそもフォームのデータ受け渡し方法なので。
単体の画像データをアップロードするのに、フォーム形式を使う必要があるのかどうか疑問です。

複数アップロードしたければPOSTを繰り返せば良いのでは。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#15

投稿記事 by helloworld1853 » 12年前

コード:

#include <stdio.h>
int CHECKLINE(int check)
{
	puts("one");
	int CHECKMIN;
	int CHECKMAX;
	int CHECKCOUNTER;
	int CHECKRETURN;

	if(check==0)
	{
		puts("two");
		CHECKRETURN=0;
	}
	else
	{
		puts("three");
		for(CHECKMIN=1,CHECKMAX=100000,CHECKCOUNTER=1;;CHECKMIN+=100000,CHECKMAX+=100000,++CHECKCOUNTER)
		{
			if(CHECKMIN<=check || check<=CHECKMAX)
			{
				CHECKRETURN=CHECKCOUNTER+1;
				break;
			}
			if(CHECKCOUNTER>=11)
			{
				CHECKRETURN=12;
				break;
			}
		}
	}
	return CHECKRETURN;
}
int main(void)
{
  FILE *fpr;
  FILE *fpw;
  char *fname_r = "test.jpg";
  char *fname_w = "copy.jpg";
  unsigned char buf[100000];
  int  size;
  int  filesize;
  int i;

  fpr = fopen( fname_r, "rb" );
  if( fpr == NULL )
  {
    printf( "cannotread¥n");
    return -1;
  }

  fpw = fopen( fname_w, "wb" );
  if( fpw == NULL )
  {
    printf( "cannotwrite¥n");
    return -1;
  }
  fseek( fpr, 0, SEEK_END );
  filesize = ftell( fpr );
  fseek( fpr, 0, SEEK_SET );
  printf("%d",filesize);
  for(i=0;i<=CHECKLINE(filesize);++i)
  {
	  size = fread( buf, sizeof( unsigned char ), 100000, fpr );
	  printf("%d",size);
	  fwrite( buf, sizeof( unsigned char ), size, fpw );
  }


  fclose( fpr );
  fclose( fpw );

  printf( "done¥n" );
  return 0;
}

作ってみましたが、

解決方法が見つかりません。

僕の言動でだいぶ話がそれてしまいましたが、

とにかくどうすればいいか

初心者の僕にも分かるようにお願いします。

サンプルコードまたはその一部も載せていただくと

ありがたいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#16

投稿記事 by softya(ソフト屋) » 12年前

前のトピックでも言われている通りバイナリに関する知識があまりにも不足しています。
なのでバイナリとテキストの違いをちゃんと理解しないとWinscok通信でまともなものが組めるはずがありません。

逆に質問です。
(1)バッファが100バイトのはずなのに10000バイトに増えているのは何故ですか?
(2)CHECKLINE関数の説明をして下さい。バイナリデータにラインなどというものはありません。
(3)CHECKRETURNが12を超えない理由は何ですか?
(4)このプログラムの実行結果と問題点をちゃんと書いて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#17

投稿記事 by helloworld1853 » 12年前

(1)バッファが100バイトのはずなのに10000バイトに増えているのは何故ですか?
>100Bよりも100000Bの方がいいと判断したと思います。寝ぼけていたので変な判断をしたと思います。すみません。
(2)CHECKLINE関数の説明をして下さい。バイナリデータにラインなどというものはありません。
>CHECKLINE関数はなんか無駄でしたね。
(3)CHECKRETURNが12を超えない理由は何ですか?
>たぶん1MBまでのファイルを想定していたからだと思います。
(4)このプログラムの実行結果と問題点をちゃんと書いて下さい。
>コメントがない
 無駄な関数がある
 1MBぐらいまでしか対応できない
 無駄な動作が多い

>結果・・・うまく動作しました。

改善したコードを載せておきます。

動作しました。

コード:

#include <stdio.h>
int main(void)
{
  FILE *fpr;
  FILE *fpw;
  char *fname_r = "test.jpg";
  char *fname_w = "copy.jpg";
  unsigned char buf[100];
  int  size;
  int  filesize;
  int i;

  fpr = fopen( fname_r, "rb" );
  if( fpr == NULL )
  {
    printf( "cannotread¥n");
    return -1;
  }

  fpw = fopen( fname_w, "wb" );
  if( fpw == NULL )
  {
    printf( "cannotwrite¥n");
    return -1;
  }
  fseek( fpr, 0, SEEK_END );//サイズ特定

  filesize = ftell( fpr );//filesizeにサイズを入れる

  fseek( fpr, 0, SEEK_SET );//初期化


  for(i=0;i<=filesize/100;++i)//ループ
  {
	  size = fread( buf, sizeof( unsigned char ), 100, fpr );
	  fwrite( buf, sizeof( unsigned char ), size, fpw );
  }


  fclose( fpr );
  fclose( fpw );
  return 0;
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#18

投稿記事 by softya(ソフト屋) » 12年前

このプログラムはジャスト100バイトの倍数サイズの時に無駄にループを回っています。
問題は出ないかもしれませんが、fwriteの代わりにsendの時には良くない処理だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#19

投稿記事 by helloworld1853 » 12年前

コード:

for(i=0;i<=filesize/100;++i)//ループ
  {
      size = fread( buf, sizeof( unsigned char ), 100, fpr );
      fwrite( buf, sizeof( unsigned char ), size, fpw );
  }

コード:

for(i=0;i<filesize/100;++i)//ループ
  {
      size = fread( buf, sizeof( unsigned char ), 100, fpr );
      fwrite( buf, sizeof( unsigned char ), size, fpw );
  }
に変えればいいという意味ですね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#20

投稿記事 by softya(ソフト屋) » 12年前

それだとまともに動かないと思います。
境界値付近のバグはデバッグ時の最優先チェック項目と言われています。つまり、それだけバグを出しやすいものなのです。
99バイト,100バイト,101バイトでまともに動く処理を検証してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#21

投稿記事 by helloworld1853 » 12年前

99、100、101動作確認!!

コード:

for(/*i=0;i<filesize/100;++i*/;;)//ループ
  {
	  size = fread( buf, sizeof( unsigned char ), 100, fpr );
	  if(size==0)
	  {
		  break;
	  }
	  fwrite( buf, sizeof( unsigned char ), size, fpw );
  }
に変更しました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#22

投稿記事 by softya(ソフト屋) » 12年前

確かに動きますね。
計算で解決する方法もあります。

コード:

const int bufsize = 100;
for(i=0;i<(filesize+bufsize-1)/bufsize ;++i)
これで何故OKなのかは考えてみてください。

さて、POSTの件ですがmultipart/form-dataを使うのかISLeさんの言われるバイナリ直(application/octet-stream?私は使ったことがないです)で良いのかって話しを検討してみてください。
こんな話もされてますね。
ISLe さんが書きました:
helloworld1853 さんが書きました:ちなみにこのプログラムは動作しました。
例えば画像データの中に'&'と同じ文字コードのバイトデータが含まれているとそこで切れてしまう気がします。


CGI.pmを使っているのでmultipart/form-dataかどうかは関係ないと思いますが、そもそもフォームのデータ受け渡し方法なので。
単体の画像データをアップロードするのに、フォーム形式を使う必要があるのかどうか疑問です。

複数アップロードしたければPOSTを繰り返せば良いのでは。
私は、ファイル名と画像データを同時に送るならmultipart/form-dataを使うしか無いとは思うのですが・・・。ただし転送は冗長で面倒になります。
それは設計の問題なので、どうしたいかはご本人が決めることです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#23

投稿記事 by helloworld1853 » 12年前

application/octet-streamの方を使いたいとおもいます。

早速 検索してみたものの、資料が少ないです。

どなたかサンプルコードもしくは資料をお願いします。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#24

投稿記事 by ISLe » 12年前

softya(ソフト屋) さんが書きました:私は、ファイル名と画像データを同時に送るならmultipart/form-dataを使うしか無いとは思うのですが・・・。ただし転送は冗長で面倒になります。
それは設計の問題なので、どうしたいかはご本人が決めることです。
helloworld1853さんが提示したCGIはファイル名を受け取る意図が微塵も感じられませんね。
何がしたいのかさっぱり分からないと感じるのは提示されたコードの何もかもですけど。

%エンコードよりMIMEコンコードは遥かに難しいと思います。
転送データ量が何倍も増えますし。

POSTするときURLに付けたパラメータってCGIで拾えませんでしたっけ。
?filename=test.bmpみたいな。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#25

投稿記事 by softya(ソフト屋) » 12年前

helloworld1853 さんが書きました:application/octet-streamの方を使いたいとおもいます。

早速 検索してみたものの、資料が少ないです。

どなたかサンプルコードもしくは資料をお願いします。
訂正。ダウンロードでは使ったことがありました。
application/octet-streamでファイル名も渡せます。

コード:

Content-Disposition: attachment; filename=xxxxx
Content-Type: application/octet-stream; name=xxxxxx
Perl&アップロードでは使ったことが無いのでperlでの受け取り方が私には分かりません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#26

投稿記事 by helloworld1853 » 12年前

なんか話がややこしくなったので

ここで整理します。(実は伝えきれなかった箇所があったので・・・)

WEBサーバに画像をアップロードするプログラムを作っていました。

namae=のあとにデータを付加し、POSTすることにより解決しようと

試みたがVisual C++でコンパイルした結果char[1000000]を確保すると

スタックオーバーフロー?的なことを起こしてしまい、

(char[100000]にしたところ画像が無事にアップロードされた、しかしそれゆえに100000B以下のファイルに限る)

動作を停止していました。

つまり僕が言いたいのは

charを1MB分確保する方法でもこの問題は解決するかもしれないということです。

また、

Content-Disposition: attachment; filename=xxxxx
Content-Type: application/octet-stream; name=xxxxxx

を利用したプログラムが完成しても

100KB分のファイルは送信できるかもしれませんが

1MB分送信しようとすると

1MB確保しただけで先ほど説明したスタックオーバーフロー的な

エラーを起こしてしまうのではということです。


これからのプログラム製作のためにもご意見をお聞かせください。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#27

投稿記事 by softya(ソフト屋) » 12年前

helloworld1853さんは、10000バイトまで送信成功していると言いましたが、ISLeさんが指摘している問題はあると私も思っています。
ISLe さんが書きました:
helloworld1853 さんが書きました:ちなみにこのプログラムは動作しました。
例えば画像データの中に'&'と同じ文字コードのバイトデータが含まれているとそこで切れてしまう気がします。
なので成功しているのは単に偶然に過ぎません。
ファイルが大きくなればなるほど、偶然に助けられる確率は減りますのでどうするのかが問題です。

あとISLeさんが提案している方法として比較的簡単な16文字列に変換して今の転送方法のまま転送するのもひとつの手です。
Perl側でファイルに書く時に16進文字列をバイナリデータに戻す作業は必要になりますが。

それとfread/fwriteでやった様にファイルサイズを超える巨大バッファは随時読みこめば必要ありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#28

投稿記事 by helloworld1853 » 12年前

>softyaさんありがとうございます。

その方法で試してみます。

ただ、
>それとfread/fwriteでやった様にファイルサイズを超える巨大バッファは随時読みこめば必要ありません。

はsendをくりかえして対応していると解釈してもよろしいでしょうか。


ちなみに今巨大なファイルを送信できるプログラムを作っています。('&'と同じ文字コードバグ未対応ですけど とりあえずここから・・・)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#29

投稿記事 by softya(ソフト屋) » 12年前

最後の部分である
send(sock,body,size,0);
をfread/sendの繰り返しに変えることで対応できます。
が、十中八九&問題に引っかかると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#30

投稿記事 by helloworld1853 » 12年前

あれから試行錯誤していますがかなり難しいです。

ソースコードもぐちゃぐちゃになり

結果もなかなかでず、

大変です。

一部だけでもいいので

ソースコードを載せていただけるとありがたいです。

よろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#31

投稿記事 by softya(ソフト屋) » 12年前

No.1とNo.17とNo.21のコードを合体するだけなんですが。
今時間が取れないので後でまた返答します(明日になるかもしれません)。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#32

投稿記事 by helloworld1853 » 12年前

ありがとうございます。

僕も引き続き挑戦します。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#33

投稿記事 by softya(ソフト屋) » 12年前

仕組みだけ説明すると
(1)現在ファイルを読み込んでいるところではファイルサイズだけを調べる。
(2)strcpy(body,"namae=");では、ここで終了。ファイル実体は後ろにコピーしない。
(3)Content-Lengthはファイルサイズ+6バイトを設定。
(4)send(sock,body,size,0);はsend(sock,body,6,0);にする。
(5) (4)の後でbufにfreadしてfreadしたsizeでbufをsendする。繰り返しの条件はファイルコピーの時と同じ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#34

投稿記事 by helloworld1853 » 12年前

コードを書いてみましたが

なぜか73バイトで停止します。

原因は何でしょうか。

コード:

#include <winsock2.h>
#include <stdio.h>
int main(void)
{
  FILE *fpr;
  //FILE *fpw;
  char *fname_r = "test.txt";
  //char *fname_w = "copy.jpg";
  struct sockaddr_in addr;
  unsigned char buf[100];
  int  size;
  int  filesize;
  int i;
  int sock;
  int ret;
 
  WSADATA wsadata;
  WSAStartup( 0x0101, &wsadata );

  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr("124.96.230.45");
  addr.sin_port = htons(80);

  sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
  if ( ret < 0 ) 
  {
      printf( "can't open http port\n" );
      return 0;
  }

  fpr = fopen( fname_r, "rb" );
  if( fpr == NULL )
  {
    printf( "cannotread¥n");
    return -1;
  }
 
  /*
  fpw = fopen( fname_w, "wb" );
  if( fpw == NULL )
  {
    printf( "cannotwrite¥n");
    return -1;
  }
  */
  fseek( fpr, 0, SEEK_END );//サイズ特定
 
  filesize = ftell( fpr );//filesizeにサイズを入れる
 
  fseek( fpr, 0, SEEK_SET );//初期化
 
  char body[] = "namae=";
  char length[100];
  char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
  sprintf( length, "Content-Length: %d\r\n", 6+filesize );
  i = strlen(length);
  length[i] = '\0';

  send(sock,head,strlen(head),0);
  send(sock,length,strlen(length),0);
  send(sock,"\r\n",2,0);
  send(sock,body,6,0);
  for(/*i=0;i<filesize/100;++i*/;;)//ループ
  {
      size = fread( buf, sizeof( unsigned char ), 100, fpr );
      if(size==0)
      {
          break;
      }
      //fwrite( buf, sizeof( unsigned char ), size, fpw );
      send(sock,(const char*)buf,size,0);
	  printf("%s",buf);
	  
  }
 
 
  fclose( fpr );
  closesocket( sock );
  return 0;
}

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#35

投稿記事 by helloworld1853 » 12年前

ちなみに

#で終わっています。

この文字もんなにか意味があるのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#36

投稿記事 by softya(ソフト屋) » 12年前

あるとしたら#の次の文字でしょうね。
というかtest.txtを転送してますが画像ファイルのはずだったのでは?

[補足]
転送している内容がわからないので検証しようがないですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#37

投稿記事 by helloworld1853 » 12年前

画像のURLは

http://r02.isearch.c.yimg.jp/image?id=0 ... 590b5e45b5

です。

test.txtはテストようです。

実際はtest.jpgです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#38

投稿記事 by softya(ソフト屋) » 12年前

バイナリエディタで見たところ74バイト目に&(0x26)があるので、これが原因です。
まぁうまくいくはずがないと思っていましたが案の定ですね。

【補足】
既に出ている
あとISLeさんが提案している方法として比較的簡単な16文字列に変換して今の転送方法のまま転送するのもひとつの手です。
Perl側でファイルに書く時に16進文字列をバイナリデータに戻す作業は必要になりますが。
を検討してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#39

投稿記事 by helloworld1853 » 12年前

突然1バイトも送れなくなりました。

お待ちしております。

コード:

#include <winsock2.h>
#include <stdio.h>
int main(void)
{
  FILE *fpr;
  //FILE *fpw;
  char *fname_r = "test.txt";
  //char *fname_w = "copy.jpg";
  struct sockaddr_in addr;
  unsigned char buf[100];
  int  size;
  int  filesize;
  int i;
  int sock;
  int ret;
 
  WSADATA wsadata;
  WSAStartup( 0x0101, &wsadata );
 
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr("124.96.230.45");
  addr.sin_port = htons(80);
 
  sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
  if ( ret < 0 ) 
  {
      printf( "can't open http port\n" );
      return 0;
  }
 
  fpr = fopen( fname_r, "rb" );
  if( fpr == NULL )
  {
    printf( "cannotread¥n");
    return -1;
  }
 
  /*
  fpw = fopen( fname_w, "wb" );
  if( fpw == NULL )
  {
    printf( "cannotwrite¥n");
    return -1;
  }
  */
  fseek( fpr, 0, SEEK_END );//サイズ特定
 
  filesize = ftell( fpr );//filesizeにサイズを入れる
 
  fseek( fpr, 0, SEEK_SET );//初期化
 
  char body[] = "namae=";
  char length[100];
  char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
  sprintf( length, "Content-Length: %d\r\n", 6+filesize );
  i = strlen(length);
  length[i] = '\0';
 
  send(sock,head,strlen(head),0);
  send(sock,length,strlen(length),0);
  send(sock,"\r\n",2,0);
  send(sock,body,6,0);
  for(/*i=0;i<filesize/100;++i*/;;)//ループ
  {
      size = fread( buf, sizeof( unsigned char ), 100, fpr );
      if(size==0)
      {
          break;
      }
      //fwrite( buf, sizeof( unsigned char ), size, fpw );
      send(sock,(const char*)buf,size,0);
      printf("%02X",buf);
      
  }
 
 
  fclose( fpr );
  closesocket( sock );
  return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#40

投稿記事 by softya(ソフト屋) » 12年前

送るデータを変えたか、何らかのエラーが起こっているものと思います。
すべてのWinsock系の関数の戻り値をチェックしてエラーがないか確認して下さい。
それと、文字列に変換せずに送れる望みはないので早めに切り替えたほうが良いと思います。

あと
printf("%02X",buf);
はbufのアドレスの値を16進で表示なので意味が無いでしょう(常に一定です)。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#41

投稿記事 by helloworld1853 » 12年前

buf[1]=30
buf[2]=0D
buf[3]=0A
buf[4]=32
buf[5]=35
 ・
  ・
  ・

という感じでひとつあたりのbufに文字が2文字入れられているのですが、

先頭の文字だけをif文で比較したいのですが、

どうすればいいでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#42

投稿記事 by softya(ソフト屋) » 12年前

よく意味がわかりません。
文字というのはcharの1バイト分(環境次第ですが、この場合は8bit)に格納されているコードのことです。
buf[1]=30だと0x30と言う16進コードで文字だと'0'で2進だと00110000です。これは表記が違うだけで全て同じものです。

>先頭の文字だけをif文で比較したいのですが、
これは上位4bitの事でしょうか?

【補足】
とにかくバイナリデータを文字列化してPOST送信しないと物事は解決しないと説明したのですが、これはその為の処理の一環なのでしょうか?
変換するのにビット演算は必要ですが比較は必要ないと思うのですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#43

投稿記事 by beatle » 12年前

helloworld1853 さんが書きました:buf[1]=30
buf[2]=0D
buf[3]=0A
buf[4]=32
buf[5]=35
 ・
  ・
  ・

という感じでひとつあたりのbufに文字が2文字入れられているのですが、

先頭の文字だけをif文で比較したいのですが、

どうすればいいでしょうか。
あなたがいう「文字」というのは、buf[1]の3や0、buf[2]の0やDのことでしょうか。
普通、C言語で「文字」といったら'a'とか'X'などの文字定数やchar型変数1個のことを指しますが、それとは違うのですね?

buf[1]の3や0は「文字」というより上位ビット、下位ビットという表現のほうが正確です。
buf[1]はunsigned char型ですから、helloworld1853さんの環境では多分8ビットの大きさがありまして、それを16進数で表すと2桁になります。
したがって、printf("%02X", buf[1]);のように表示すると、buf[1]の8ビットが2桁の16進数「30」として表示されます。
同様にbuf[2]も8ビットの大きさの変数ですから、printf("02X", buf[2]);のように表示すると、2桁の16進数「0D」として表示されます。

このような8ビットデータの上位4ビットを取り出して比較するには、次のようにします。

コード:

if ((buf[1] & 0xf0) == (buf[2] & 0xf0)) {
    // buf[1]とbuf[2]の上位4ビットは等しい
}
& 0xf0
という書き方がミソです。この記述によって上位4ビットを取り出せます。
buf[1] & 0xf0 == 0x30
となるわけです。

同様に、下位4ビットを取り出して比較するには、0xf0を0x0fにします。
buf[1] & 0x0f == 0x00
となります。

ここまで、上位4ビット同士を比較する方法を示しましたが、この技術がhelloworld1853さんのプログラムにどう役立つか僕は想像ができません。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#44

投稿記事 by helloworld1853 » 12年前

少し時間が空きましたが

プログラムを作りました。

このプログラムはtest.jpgをwebページにpostするプログラムです。

&対策として、バイナリの

30 A6 7Aを

DA KG HKというように

変換して送信します。

1=A
2=B
3=C
4=D
5=E
6=F

というふうに変換して対策しています。

送信するサイズは倍になってしまいますが

cgiを編集しやすいなど実装が容易なので

この方法にしました。(c言語もできませんが、perlはもっとできないのでcgiはあまり編集したくないのです。)

実はまだcgiのほうはまだ変換機能を載せていません。

では、どうやってpostが成功したか判断するのかって考える人もいるかもしれませんが

それはsendのかわりにfwriteを使いたいと思います。

copy.txtに書き込みABDEAみたいに文字が書き込まれたら成功という感じで進めていこうと思いました。

ソースコードです。

コード:

# pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>

int main(void)
{
	unsigned char sample[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
		0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
	unsigned char    ABC[]={0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,//A-J
		0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50};//K-T

	FILE *fpr;
	FILE *fpw;
	char *fname_r = "test.jpg";
	char *fname_w = "copy.txt";
	struct sockaddr_in addr;
	unsigned char buf[10000];
	unsigned char sendbuf[20000];
	//unsigned char buf1[100];
	int  size;
	int  filesize;
	int I;
	int i;
	int i2;
	int i3;
	int sock;
	int ret;

	WSADATA wsadata;
	WSAStartup( 0x0101, &wsadata );

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("125.172.195.118");
	addr.sin_port = htons(80);

	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) 
	{
		printf( "can't open http port\n" );
		//return 0;
	}

	fpr = fopen( fname_r, "rb" );
	if( fpr == NULL )
	{
		printf( "cannotread\n");
		return -1;
	}

	 fpw = fopen( fname_w, "wb" );
	 if( fpw == NULL )
	 {
		 printf( "書込用 %sファイルが開けません\n", fname_w );
		 return -1;
	 }

	fseek( fpr, 0, SEEK_END );//サイズ特定

	filesize = ftell( fpr );//filesizeにサイズを入れる

	printf("%d\n",filesize);

	fseek( fpr, 0, SEEK_SET );//初期化

	char body[] = "namae=";
	char length[100];
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
	sprintf( length, "Content-Length: %d\r\n", 6+filesize*3 );
	i=strlen(length);
	length[i+1]='\0';

	send(sock,head,strlen(head),0);
	send(sock,length,strlen(length),0);
	send(sock,"\r\n",2,0);
	send(sock,body,6,0);
	for(I=0;;)//ループ
	{
		size = fread( buf, sizeof( unsigned char ), 10000, fpr );
		printf("%d\n",size);

		if(size==0)
		{
			break;
		}
		fwrite( buf, sizeof( unsigned char ), size, fpw );
		int counter=0;
		for(i=0;size!=i;++i)
		{		
			for(i2=0;i2!=17;++i2)
			{
				if((sample[i2] & 0xf0)==(buf[i] & 0xf0))//0xAB
				{
					sendbuf[I]=ABC[i2];

					for(i3=0;i3!=17;++i3)
					{
						if((sample[i3] & 0x0f)==(buf[i] & 0x0f))
						{
							I++;
							sendbuf[I]=ABC[i3]; 
							
							break;
						}

					}
					I++;
					break;
					
				}
				
			}


		}
		send(sock,(const char *)sendbuf,I,0);
		fwrite( sendbuf, sizeof( unsigned char ), I, fpw );
	}

	fclose( fpw );
	fclose( fpr );
	closesocket( sock );
	return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#45

投稿記事 by softya(ソフト屋) » 12年前

perlにはpack()関数があるので16進文字列→バイナリデータ変換が容易です。
http://mikeneko.creator.club.ne.jp/~lab ... transform/
なのでわざわざ変わった文字列に変換するよりも16進数文字列(HEX文字列)化するほうが後々楽ですし動作確認も簡単になります。

あとエラー処理は実装しなかったのですね。
原因不明だったが直ったらからOKだと思っていなら、いづれ実装する必要があると思うので今のうちにやっておくべきだと思います。

ちなみに16進数文字列への変換は、こうすればシンプルになります。まぁ関数化する必要もないんですが。

コード:

#include <stdio.h>
#define DATA_SIZE (4)

char ConvHex(int bit4)
{
	const char hexTable[] = { 
		'0', '1', '2', '3', '4', '5', '6', '7',
		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
	};
	return hexTable[bit4];
}

int main(void)
{
	int i;
	char data[DATA_SIZE] = { 0x01, 0x55, 0x19, 0xff };
	char hexBuf[DATA_SIZE*2+1];
	
	for( i=0; i<DATA_SIZE ; i++ ) {
		hexBuf[i*2] = ConvHex((data[i]>>4)&0x0f);
		hexBuf[i*2+1] = ConvHex(data[i]&0x0f);
		
	}
	hexBuf[i*2] = '\0';
	
	printf( "hex = %s\n", hexBuf );
	
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#46

投稿記事 by helloworld1853 » 12年前

pack関数は僕にとって難しいです。

丸投げで失礼だとわかっています。

実装お願いします。

コード:

#!/usr/local/bin/perl
use CGI;
$q = new CGI;
$Name = $q->param('namae');#1~100000
print "Content-type: text/html\n\n";
print "<META http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n";
print $Name;
open (OUT,">test.txt");
print OUT $Name;
close (OUT);
print 'sucess';
exit;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#47

投稿記事 by softya(ソフト屋) » 12年前

ここ10年ぐらいPerlを触っていないので自信が無い上に動作確認してませんが、次のようにするだけで良いはずです。

コード:

#!/usr/local/bin/perl
use CGI;
$q = new CGI;
$hex = $q->param('namae');#1~100000
print "Content-type: text/html\n\n";
print "<META http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n";
print $Name;
$bindata = pack("H*",$hex);
open (OUT,">test.bmp");
binmode(OUT);
print OUT $bindata;
close (OUT);
print 'sucess';
exit;
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#48

投稿記事 by helloworld1853 » 12年前

また一バイトとも送れなくなりました。

検査した結果どうやらソースコードに問題があるようです。

問題はないと思いますが・・・

みなさんどう考えますか。

ちなみに明日エラー番号を取得する予定です。

コード:

# pragma comment(lib, "ws2_32.lib")
			#include <winsock2.h>
		#include <stdio.h>
		char ConvHex(int bit4)
		{
			const char hexTable[] = { 
				'0', '1', '2', '3', '4', '5', '6', '7',
				'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
			};
			return hexTable[bit4];
		}
		int main(void)
		{
		  FILE *fpr;
		  FILE *fpw;
		  FILE *fptxt;
		  char *fname_r = "test.jpg";
		  char *fname_w = "copy.jpg";
		  char *fname_txt = "test.txt";
		  struct sockaddr_in addr;
		  unsigned char buf[1000];
		  unsigned char sendbuf[2001];
		  int  size;
		  int  filesize;
		  int i;
		  int sock;
		  int ret;
 
		  WSADATA wsadata;
		  WSAStartup( 0x0101, &wsadata );
 
		  addr.sin_family = AF_INET;
		  addr.sin_addr.s_addr = inet_addr("125.172.195.118");
		  addr.sin_port = htons(80);
 
		  sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
		  ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
		  if ( ret < 0 ) 
		  {
			  printf( "can't open http port\n" );
			  return 0;
		  }
 
		  fpr = fopen( fname_r,"rb" );
		  if( fpr == NULL )
		  {
			printf( "cannotread¥n");
			return -1;
		  }
 
  
		  fpw = fopen( fname_w,"wb" );
		  if( fpw == NULL )
		  {
			printf("cannotwrite\n");
			return -1;
		  }

		  fptxt = fopen( fname_txt, "wb" );
		  if( fptxt == NULL )
		  {
			printf("cannotwrite\n");
			return -1;
		  }
  
		  fseek( fpr, 0, SEEK_END );//サイズ特定
 
		  filesize = ftell( fpr );//filesizeにサイズを入れる
 
		  fseek( fpr, 0, SEEK_SET );//初期化
 
		  char body[] = "namae=";
		  char length[100];
		  char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
		  sprintf( length, "Content-Length: %d\r\n", 6+filesize*2 );
		  i = strlen(length);
		  length[i] = '\0';
 
		  send(sock,head,strlen(head),0);
		  send(sock,length,strlen(length),0);
		  send(sock,"\r\n",2,0);
		  send(sock,body,6,0);
		  for(;;)//ループ
		  {
			  size = fread( buf, sizeof( unsigned char ), 100, fpr );
			  if(size==0)
			  {
				  break;
			  }
			  for( i=0; i<size ; i++ )
			  {
				  sendbuf[i*2] = ConvHex((buf[i]>>4)&0x0f);
				  sendbuf[i*2+1] = ConvHex(buf[i]&0x0f);
				  printf("%02X",buf[i]);
			  }
			  //sendbuf[i*2] = '\0';


			  fwrite( buf, sizeof( unsigned char ), size, fpw );
			  fwrite( sendbuf, sizeof( unsigned char ), size*2, fptxt );
			  send(sock,(const char*)sendbuf,size*2,0);
			  //printf("%02X",buf);
      
		  }
 
		  fclose( fpw );
		  fclose( fpr );
		  fclose( fptxt );
		  closesocket( sock );
		  return 0;
		}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#49

投稿記事 by softya(ソフト屋) » 12年前

localhsotにPOSTしているのでなければ、WireSharkなどでパケットを確認できるはずです。
どんなパケットが飛んでいるか確認してみてください。
「WIRESHARK(ワイアシャーク)」
http://homepage2.nifty.com/protocol/wireshark/
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#50

投稿記事 by ISLe » 12年前

%エンコードすればCGI.pmが勝手にデコードしてくれるような気もしますが。

Content-Lengthも変更する必要があるのでは?

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#51

投稿記事 by helloworld1853 » 12年前

みなさまありがとうございます。

wiresharkを使用した結果、

一応通信されているようです。

緑色のところと赤色のところがあります。

正直僕が見てもよくわかりません。

ほかにのせる必要がある情報はありますか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#52

投稿記事 by softya(ソフト屋) » 12年前

ターゲットサーバーだけにフィルタリングしたほうが良いと思います。
ip.src == ipアドレス or ip.dst == ipアドレス
通信系の開発には不可欠なツールだと思うので使い方は出来れば覚えたほうが良いですよ。

「Hokkaido.cap#1 Wiresharkの使い方(基礎編)」


で、赤または黒で表示されているパケットはエラーがあると思います。
右クリック → copy → summary(TEXT)でエラー内容をコピペしてもらえますか。

こんな感じ。
75773 200.568446 192.168.1.17 192.168.1.14 TCP 59694 > microsoft-ds [RST, ACK] Seq=1057 Ack=741 Win=0 Len=0
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#53

投稿記事 by helloworld1853 » 12年前

赤いエラー3つのせておきます。

1 0.000000 192.168.1.2 124.96.235.19 TCP 50369 > http [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=8

3 0.047195 192.168.1.2 124.96.235.19 TCP 50369 > http [ACK] Seq=1 Ack=1 Win=66304 Len=0

4 0.047558 192.168.1.2 124.96.235.19 TCP [TCP segment of a reassembled PDU]

鑑定お願いします。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#54

投稿記事 by helloworld1853 » 12年前

ISLeさんに指摘されて気づいたのですが、

content-lengthはいまのままで大丈夫ですよね。

wiresharkを見た感じ content-lengthに問題がありそうだったので・・・

勘違いだったらすみません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#55

投稿記事 by softya(ソフト屋) » 12年前

バイナリの長さの2倍であるのなら問題無いと思います。
エラーについては全部くエラーに成っている雰囲気なのでconnect失敗とかが考えれますが全パケットを詳細に見ないとなんとも言えません。
が見るのも大変なので、とりあえずエラー処理を入れてもらったほうが話が早いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#56

投稿記事 by helloworld1853 » 12年前

http://s1.muryo.etowns.net/~yamada_mama_papa/

このurlにアクセスできないことと何か関係があるのでしょうか。

一応 無料eタウンには連絡を入れておいたのですが・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#57

投稿記事 by softya(ソフト屋) » 12年前

なんとも言えません。
その原因を探るためにもエラー処理の追加をお願いします。
helloworld1853 さんが書きました:このurlにアクセスできないことと何か関係があるのでしょうか。
一応 無料eタウンには連絡を入れておいたのですが・・・
無料サーバーですので時間帯によってはアクセス不能に成るのは仕方ないかもしれません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#58

投稿記事 by helloworld1853 » 12年前

最後のほうに

コード:

printf( "\n%s", strerror( errno ) );
を追加したところ

No error と表示されます。

どうやらcgiが悪いらしいです。

初期のcgiにアクセスしてみたところ、

エラーが表示されました。

http://s1.muryo.etowns.net/~yamada_mama_papa/test.cgi


今、知恵袋で質問しているので、

そちらもよろしくお願いします。

http://detail.chiebukuro.yahoo.co.jp/qa ... 1087009095

(やはりここはc言語専用のサイトなので知恵袋に質問させていただきました。)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#59

投稿記事 by softya(ソフト屋) » 12年前

規約に則り知恵袋と相互リンクして下さい。
それと最後にエラーをチェックしても意味が無いので全部の関数の戻り値をちゃんとチェックしてくださいね(手抜きしてもエラーはチェックできません)。

エラーを見る限りはパーミッション設定をミスっているものと思われます。

[補足]
無料でEタウンでこんな記述を見つけましたが大丈夫ですか?
※cgiへのアクセスに関しまては以下のような制限を設けております。
アクセス時の状況 表示結果
s○.muryo.etowns.netに作成されたホームページからcgiを呼び出した場合 正常に表示されます
URLを直接入力した場合 正常に表示されます
s○.muryo.etowns.net以外のホームページからcgiを呼び出した場合 403 Forbidden(アクセス権限がありません)
ブックマークを利用した場合 古いブラウザでは403 Forbiddenと出る場合があります
http://muryo-de.mydns.jp/cgi.php

無料でEタウンの想定外の使い方をしているのは規約違反ですので、規約の範囲内で使うようにしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#60

投稿記事 by helloworld1853 » 12年前

cgiが動くようになりました。

しかし相変わらず1バイトも・・・

あとエラー処理というものがよくわからないので、

とりあえずテストプログラムを作って

検証してみた結果・・・

5バイトだけ送信できました。

バイナリデータは

31 32 34 35 36

です。

プログラムのソースコードを見ればわかると思いますが

期待していたデータは31 32 33 34 35 36 37 38 39です。

いろいろ試していたらまた一バイトとも送れなくなりました。

値を313233に変更しても

31 32 34 35 36のままです。

返信を見てみると途中で切れています。

このことも関係あるのでしょうか。    (問題解決を早めるために返信されたデータを取得する機能を装備しています。
                         とある書籍のソースコードです。C/C++辞典です。それを少し改良したものです。
                         ただデータ取得機能はそのままです。以下にソースコードをのせます。)

コード:

# pragma comment(lib, "ws2_32.lib")
#include <stdio.h>
#ifdef _MSC_VER
#include <winsock2.h>
#else
#include <sys/unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

int main( void )
{
	int sock, ret;
	struct sockaddr_in addr;

#ifdef _MSC_VER
	{
	WSADATA wsadata;
	WSAStartup( 0x0101, &wsadata );
	}
#endif

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("124.96.227.48");
	addr.sin_port = htons(80);
	
	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) {
		printf( "can't open http port\n" );
		return 0;
	}
	
	char body[] = "namae=313233\r\n";
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n\r\n";
	char length[100];
	sprintf( length, "Content-Length: %d\r\n", strlen(body) );
	printf("\n%d\n",strlen(body));
	
	int n = 0;
	n += send( sock, head, strlen(head), 0 );
	n += send( sock, length, strlen(length), 0 );
	n += send( sock, "\r\n", 2, 0 );
	n += send( sock, body, strlen(body), 0 );
	printf( "send: %d\n", n );
	
	char buf[256];
	printf( "http recv data\n" );
	printf( "=============================\n" );
	while ( 1 ) {
		n = recv( sock, buf, sizeof(buf)-1, 0 );
		if ( n <= 0 ) break;
		buf[ n ] = '\0';
		printf( buf );
	}
#ifdef _MSC_VER
	closesocket( sock );
#else
	close( sock );
#endif
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#61

投稿記事 by softya(ソフト屋) » 12年前

前に書いた件は別のサイトからのリンクは禁止でURLで直接アクセスなら許可するって事でした。
なので、リンクをクリックしても必ずそれはエラーになります。URLコピペで直接アクセスならアクセスできました。

こちらで最新コードを試してみましたが送信は成功します。
ただ、受信はプログラムコードの書き方が悪いので受信できてはいません。正確に書くとパケットは返って来ているが受け取れていないって事ですね。
WireSharkのログで見ても受信だけ失敗しています。

WireSharkでやり取りされたパケットです(日本語はWireSharkの都合上文字化けしてます)。

コード:

POST /~yamada_mama_papa/test.cgi HTTP/1.0

Host: s1.muryo.etowns.net



Content-Length: 14



namae=313233

HTTP/1.1 200 OK

Date: Fri, 11 May 2012 15:04:57 GMT

Server: Apache/1.3.33 (Unix)  (Vine/Linux) mod_throttle/3.1.2 mod_layout/3.2 mod_gzip/1.3.26.1a mod_ssl/2.8.22 OpenSSL/0.9.7d

X-Powered-By: ModLayout/3.2

Cache-Control: no-cache

Connection: close

Content-Type: text/html







 <!-- Headerad code start -->



<META http-equiv="refresh" content="0;URL=http://s1.muryo-de.mydns.jp

/~yamada_mama_papa/test.cgi"><!-- nhewsh[PC]hjyewv -->
<center>

 <!-- adaccess code start -->
<img style="POSITION:absolute;display:block;" src="http://s1.muryo.etowns.net:80/adaccess/access.cgi?ref=http://s1.muryo.etowns.net:80/~yamada_mama_papa/test.cgi" width="1" height="1">
 <!-- adaccess code end -->





<div id="ad_scroll_etowns" style="position:relative; left: 0; top: 0;z-index:120;">

<TABLE border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff" hspace="0" vspace="0"><TR>
<td hspace="0" vspace="0" width="234"><font size="-1"><b><a style="color: blue;text-decoration:underline;" href="http://muryo.etowns.net/" target="_blank">.......z.[...y.[.W</a></b></font><br><font style="color: black;" size=-2>.........^...T.[.o.[.E......E.^.E...B...o.^...A...........p...\.....B</font><br><font size="-2"><a style="color: green;text-decoration:underline;" href="http://muryo.etowns.net/" target="_blank">http://muryo.etowns.net/</a></font></td><td hspace="0" vspace="0"><font size="-1">.@</font></td>
<td hspace="0" vspace="0" width="234"><font size="-1"><b><a style="color: blue;text-decoration:underline;" href="http://zimente.3utilities.com/" target="_blank">PC.........e.i...X.\.t.g</a></b></font><br><font style="color: black;" size="-2">.f.t...O...f.B.X.N.N...[...A.b.v...........e.i...
もう少し調べてみます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

トントン
記事: 100
登録日時: 13年前

Re: webサーバにファイルをPOSTする方法。

#62

投稿記事 by トントン » 12年前

色々、ここじゃないかなぁと思っていた箇所が全然違ったので割と凹んだorz
下記ソースに関して言えば38行目(元ソース37行目)の最後の\r\n、多分1個多いです。
(ipアドレスも違う)

後、僕のローカル鯖では
31 32 33 34 35 36 37 38 39のテストは
そのままバイナリデータに反映されました。
helloworld1853 さんが書きました:

コード:

# pragma comment(lib, "ws2_32.lib")
#include <stdio.h>
#ifdef _MSC_VER
#include <winsock2.h>
#else
#include <sys/unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

int main( void )
{
	int sock, ret;
	struct sockaddr_in addr;

#ifdef _MSC_VER
	{
	WSADATA wsadata;
	WSAStartup( 0x0101, &wsadata );
	}
#endif

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("124.96.227.48");
	addr.sin_port = htons(80);
	
	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) {
		printf( "can't open http port\n" );
		return 0;
	}
	
	char body[] = "namae=313233\r\n";
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\n
Host: s1.muryo.etowns.net\r\n\r\n";  ←ここ
	char length[100];
	sprintf( length, "Content-Length: %d\r\n", strlen(body) );
	printf("\n%d\n",strlen(body));
	
	int n = 0;
	n += send( sock, head, strlen(head), 0 );
	n += send( sock, length, strlen(length), 0 );
	n += send( sock, "\r\n", 2, 0 );
	n += send( sock, body, strlen(body), 0 );
	printf( "send: %d\n", n );
	
	char buf[256];
	printf( "http recv data\n" );
	printf( "=============================\n" );
	while ( 1 ) {
		n = recv( sock, buf, sizeof(buf)-1, 0 );
		if ( n <= 0 ) break;
		buf[ n ] = '\0';
		printf( buf );
	}
#ifdef _MSC_VER
	closesocket( sock );
#else
	close( sock );
#endif
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#63

投稿記事 by softya(ソフト屋) » 12年前

受信処理が悪いというわけでもなさそうですが、色々試しましたが何かサーバーの動作が安定しませんね。
ローカルサーバーで試してみます。

ちなみにエラーチェックは、こちらを参考にしてください。
「WinScokプログラミング第6章」
http://www.geocities.jp/playtown1056/program/ws_6.htm
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#64

投稿記事 by softya(ソフト屋) » 12年前

トントンさんの言われる通りにすればローカルでは成功しましたが、本当のサーバーではHOSTが見つからないエラーが返却されています。
2961 16.209283 221.113.141.179 192.168.1.17 ICMP Destination unreachable (Host unreachable)
つまり、サーバー側の問題の何かに引っかかっています。
なにか無料eタウンが書いていないガード条件があるんでしょうね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#65

投稿記事 by helloworld1853 » 12年前

\r\nを消すと治りました。

txtへの書き込みは成功しましたが、

jpgへの書き込みは相変わらずです。

そしてここから意味不明なことがおきました。

cgiのtest.jpgをtest.txtにかえました。

そのあとブラウザでhttp://s1.muryo-de.mydns.jp/~yamada_mama_papa/test.txtにアクセスすると・・・

拡張子がtxtにもかかわらず画像が見れます。

ほかの拡張子でも試してみます。

詳細がわかる人お願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#66

投稿記事 by softya(ソフト屋) » 12年前

helloworld1853 さんが書きました:cgiのtest.jpgをtest.txtにかえました。

そのあとブラウザでhttp://s1.muryo-de.mydns.jp/~yamada_mama_papa/test.txtにアクセスすると・・・

拡張子がtxtにもかかわらず画像が見れます。

ほかの拡張子でも試してみます。
そこはブラウザの問題だと思うので追求しても意味が無いかなぁと思います。
test.txtと言っても中身はjpegなんですよね?
やるとしたら違うブラウザで表示して見ることぐらいでしょうか。

ちなみにFireFoxだとダウンロードされました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#67

投稿記事 by helloworld1853 » 12年前

しかし

なぜtest.jpgでは1バイトも表示できないけれどtest.txtでは正しく?表示されたのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#68

投稿記事 by softya(ソフト屋) » 12年前

helloworld1853 さんが書きました:しかし

なぜtest.jpgでは1バイトも表示できないけれどtest.txtでは正しく?表示されたのでしょうか。
ブラウザ・キャッシュの問題かしれません。
出来上がったtest.jpgをFTPなどでこちらに再コピーして内容を確認してみてください。
バイナリエディタなどで転送元と転送先で同じ内容であるか確認するべきです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#69

投稿記事 by helloworld1853 » 12年前

FFFTPでダウンロードしたところ

無事にpostされていました。

みなさま長い間ありがとうございました。

皆様に一応聞きますが

最終ソースコードは載せたほうがいいですか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#70

投稿記事 by softya(ソフト屋) » 12年前

時々通信エラーになるという問題は解決していないと思いますのでエラー処理は入れたほうが良いと思います。
それと元々の課題の1MBが送れるかちゃんと確認しないと意味が無いのでは?
それらが済んだらソースを公開をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

トントン
記事: 100
登録日時: 13年前

Re: webサーバにファイルをPOSTする方法。

#71

投稿記事 by トントン » 12年前

一応言っておくと

コード:

print $Name;
これは下記ソースだと空白しか表示されません。
ただ、セキュリティには僕も疎いのであまり詳細は述べれませんが
単純に渡ってきたものを特別な処理を施さないで表示させようと思っているのであれば、
削除か放置が無難だと思っています。

コード:

#!/usr/local/bin/perl
use CGI;
$q = new CGI;
$hex = $q->param('namae');#1~100000
print "Content-type: text/html\n\n";
print "<META http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n";
print $Name;  ←ここ。ただし、単純に表示させようと思っているなら表示させるなんて考えないで削除するのが無難。
$bindata = pack("H*",$hex);
open (OUT,">test.bmp");
binmode(OUT);
print OUT $bindata;
close (OUT);
print 'sucess';
exit;
オフトピック
とはいえ、テストするならレンタル鯖ではなく
ローカル鯖を使用したほうが良い様な気もしますが。。。
最後に編集したユーザー トントン on 2012年5月12日(土) 23:59 [ 編集 1 回目 ]

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#72

投稿記事 by helloworld1853 » 12年前

トントンさんありがとうございます。

早速試してみます。

softyaさん

1MB 送信できることは確認しました。

あと、

エラー処理というのは

・ソケットの破棄処理を追加
・ipアドレスがたびたび変わるのでホスト名からipアドレスを取得する処理を追加
・通信したさいに1バイトも遅れなくなったらエラー表示

を追加するだけでいいでしょうか。

ちょっと今日は遅いので明日になりますけど・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#73

投稿記事 by softya(ソフト屋) » 12年前

既に書いた
ちなみにエラーチェックは、こちらを参考にしてください。
「WinScokプログラミング第6章」
http://www.geocities.jp/playtown1056/program/ws_6.htm
最低限として、上のサイト並の処理するということです。
つまり、WinSock関数の戻り値は全てチェックして1つも漏らしてはいけません。
今の処理ははっきり言ってだだ漏れ状態です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#74

投稿記事 by helloworld1853 » 12年前

動作確認済みです。

コード:

# pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
char ConvHex(int bit4)
{

	const char hexTable[] = 
	{ 

		'0', '1', '2', '3', '4', '5', '6', '7',

		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

	};

	return hexTable[bit4];
}
int main(void)
{

	FILE *fpr;
	char *fname_r = "test.jpg";
	char ServerName[] = "s1.muryo.etowns.net";           // 接続先のホスト名
	struct sockaddr_in addr;
	unsigned char buf[1000];
	unsigned char sendbuf[2001];
	PHOSTENT phostent;                          // サーバの情報を指すポインタ
	unsigned long ulIPAddress;                  // サーバのIPアドレス格納変数
	int  size;
	int  filesize;
	int i;
	int sock;
	int ret;
 
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2,0), &wsadata);
	
	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	if(sock == INVALID_SOCKET)
	{
		printf("ソケット作成失敗です。\n");
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		return -1;
	}

	// サーバのIPアドレス取得
	ulIPAddress = inet_addr(ServerName);        // IPアドレス取得
	// inet_addr()関数が失敗 ServerNameがホスト名であった場合下の処理に入る
	if(ulIPAddress == -1)
	{
		if( (phostent = gethostbyname(ServerName)) != NULL)
		{
			ulIPAddress = *((unsigned long *)(phostent->h_addr));
		}
		else
		{
			printf("ホストアドレス取得失敗です。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			closesocket(sock);                    // ソケットの破棄
			return -1;            
		}
	}



	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = ulIPAddress;
	addr.sin_port = htons(80);
 


	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) 
	{
		printf( "HTTPポートが開けません。\n" );
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		closesocket(sock);
		return -1;
	}
 
	fpr = fopen( fname_r,"rb" );
	if( fpr == NULL )
	{
		printf("ファイルが読み込めません。\n");
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		return -1;
	}

	fseek( fpr, 0, SEEK_END );//サイズ特定
 
	filesize = ftell( fpr );//filesizeにサイズを入れる
 
	fseek( fpr, 0, SEEK_SET );//初期化
 
	char body[] = "namae=";
	char length[100];
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
	sprintf( length, "Content-Length: %d\r\n", 6+filesize*2 );
	i = strlen(length);
	length[i+1] = '\0';

	if(send(sock,head,strlen(head),0) == SOCKET_ERROR)
	{
        printf("サーバへの送信失敗です\n");
        printf("エラー%dが発生しました\n", WSAGetLastError());
        shutdown(sock, SD_BOTH);                        // 送受信を無効にする
        closesocket(sock);                        // ソケットの破棄
        return -1;
	}
	send(sock,length,strlen(length),0);
	send(sock,"\r\n",2,0);
	send(sock,body,6,0);
	for(;;)//ループ
	{
		size = fread( buf, sizeof( unsigned char ), 1000, fpr );
		if(size==0)
		{
			break;
		}
		for( i=0; i<size ; i++ )
		{
			sendbuf[i*2] = ConvHex((buf[i]>>4)&0x0f);//16進数文字列
			sendbuf[i*2+1] = ConvHex(buf[i]&0x0f);   //16進数文字列
			printf("%02X",buf[i]);
		}
		send(sock,(const char*)sendbuf,size*2,0);
	}
	WSACleanup();
	fclose( fpr );
	shutdown(sock, SD_BOTH);
	closesocket( sock );
	return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#75

投稿記事 by softya(ソフト屋) » 12年前

申し訳ないですがエラーチェックがすごく中途半端です。例示したコードをちゃんと見てもらましたか?
現在は困っていないかもしれませんが、後々絶対困ることになりますよ。
エラーが起こって転送失敗しても気にしない程度のプログラムなら構いませんが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#76

投稿記事 by helloworld1853 » 12年前

winsock初期化の処理が丸々抜けていることでしょうか。

wVersionRequestedが定義されていないと出てしまうのでまだ実装できていません。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#77

投稿記事 by helloworld1853 » 12年前

とりあえず完成しました。

エラー処理はここまででいいかな

と思っています。

ただ送信が終わってもプログラムが終了しないのはなぜですか。

いつもは最後に

続行するにはなにかキーを押してください

と出ますが このプログラムでは出ません。

コード:

# pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>

//#define WIN32_LEAN_AND_MEAN
char ConvHex(int bit4)
{

	const char hexTable[] = 
	{ 

		'0', '1', '2', '3', '4', '5', '6', '7',

		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

	};

	return hexTable[bit4];
}
int main(void)
{

	FILE *fpr;
	char *fname_r = "test.jpg";
	char ServerName[] = "s1.muryo.etowns.net";           // 接続先のホスト名
	struct sockaddr_in addr;
	unsigned char buf[1000];
	unsigned char sendbuf[2001];
	PHOSTENT phostent;                          // サーバの情報を指すポインタ
	unsigned long ulIPAddress;                  // サーバのIPアドレス格納変数
	int  size;
	int  filesize;
	int i;
	int sock;
	int ret;
 WORD wVersionRequested = MAKEWORD(1, 1); 
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2,0), &wsadata);
	int nErrorStatus;

    nErrorStatus = WSAStartup(wVersionRequested, &wsadata);
    if(atexit((void (*)(void))(WSACleanup))){    // 終了時にWinSockのリソースを解放
        printf("atexit(WSACleanup)失敗\n");
        return -1;
    }
    if(nErrorStatus != 0){
        printf("初期化失敗です\n");
        return -1;
    }
    else{
        if(LOBYTE( wsadata.wVersion ) == 1
            && HIBYTE( wsadata.wVersion ) == 1){    // 要求したバージョンと同一か確認
            printf("WinSock初期化成功\n");
        }
        else{
            printf("WinSock初期化失敗です\n");
            return -1;
        }
    }


	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	if(sock == INVALID_SOCKET)
	{
		printf("ソケット作成失敗です。\n");
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		return -1;
	}

	// サーバのIPアドレス取得
	ulIPAddress = inet_addr(ServerName);        // IPアドレス取得
	// inet_addr()関数が失敗 ServerNameがホスト名であった場合下の処理に入る
	if(ulIPAddress == -1)
	{
		if( (phostent = gethostbyname(ServerName)) != NULL)
		{
			ulIPAddress = *((unsigned long *)(phostent->h_addr));
		}
		else
		{
			printf("ホストアドレス取得失敗です。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			closesocket(sock);                    // ソケットの破棄
			return -1;            
		}
	}



	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = ulIPAddress;
	addr.sin_port = htons(80);
 


	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) 
	{
		printf( "HTTPポートが開けません。\n" );
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		closesocket(sock);
		return -1;
	}
 
	fpr = fopen( fname_r,"rb" );
	if( fpr == NULL )
	{
		printf("ファイルが読み込めません。\n");
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		return -1;
	}

	fseek( fpr, 0, SEEK_END );//サイズ特定
 
	filesize = ftell( fpr );//filesizeにサイズを入れる
 
	fseek( fpr, 0, SEEK_SET );//初期化
 
	char body[] = "namae=";
	char length[100];
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
	sprintf( length, "Content-Length: %d\r\n", 6+filesize*2 );
	i = strlen(length);
	length[i+1] = '\0';

	if(send(sock,head,strlen(head),0)== SOCKET_ERROR ||
	   send(sock,length,strlen(length),0)== SOCKET_ERROR ||
	   send(sock,"\r\n",2,0)== SOCKET_ERROR||
	   send(sock,body,6,0)== SOCKET_ERROR)
	{
        printf("サーバへの送信失敗です\n");
        printf("エラー%dが発生しました\n", WSAGetLastError());
        shutdown(sock, SD_BOTH);                        // 送受信を無効にする
        closesocket(sock);                        // ソケットの破棄
        return -1;
	}

	for(;;)//ループ
	{
		size = fread( buf, sizeof( unsigned char ), 1000, fpr );
		if(size<0)
		{
			printf("ファイルが読み込めません。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			shutdown(sock, SD_BOTH);                        // 送受信を無効にする
			closesocket(sock);                        // ソケットの破棄
			return -1;
		}
		for( i=0; i<size ; i++ )
		{
			sendbuf[i*2] = ConvHex((buf[i]>>4)&0x0f);//16進数文字列
			sendbuf[i*2+1] = ConvHex(buf[i]&0x0f);   //16進数文字列
			printf("%02X",buf[i]);
		}
		if(send(sock,(const char*)sendbuf,size*2,0)== SOCKET_ERROR)
		{
			printf("サーバへの送信失敗です。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			shutdown(sock, SD_BOTH);                        // 送受信を無効にする
			closesocket(sock);                        // ソケットの破棄
			return -1;		
		}
	}
	WSACleanup();
	fclose( fpr );
	shutdown(sock, SD_BOTH);
	closesocket( sock );
	return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#78

投稿記事 by softya(ソフト屋) » 12年前

helloworld1853 さんが書きました:winsock初期化の処理が丸々抜けていることでしょうか。

wVersionRequestedが定義されていないと出てしまうのでまだ実装できていません。
wVersionRequestedって自分で宣言する変数ですよ。

send()やshutdown()やclosesocket()でもエラーチェックは行う必要があります。※shutdown()では例示したプログラムでも行なっていませんが本当はやるべきです。
それといま気づきましたが、WSACleanup()を先にやってはいけません。

「補足」
何処で止めるかは自由ですのでお任せします。
ただ、完全な状態では無いということはお知らせしておきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#79

投稿記事 by helloworld1853 » 12年前

まだテスト段階なのでまだそこまでの精度を要求していませんのでエラー処理はここら辺にします。

さてちょっとした問題が発生しました。

どうやらファイル名も渡す必要があるようです。

(拡張子が*.gif *.jpg *.bmpなどの拡張子が存在しているのでjpgだけ対応というのはよくよく考えてみるとおかしいですね。)

cgiを作ってみたので見ていただけますか。

送信側がfilenameにファイル名をpostし、

それをcgiが受け取るという形です。

コード:

#!/usr/local/bin/perl
use CGI;
$q = new CGI;
$hex = $q->param('namae');
$filename = $q->param('filename');#ここの箇所を追加しました。
print "Content-type: text/html\n\n";
print "<META http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n";
$bindata = pack("H*",$hex);
open (OUT,&filename);#ここの箇所を変更しました。
binmode(OUT);
print OUT $bindata;
close (OUT);
print 'sucess';
exit;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#80

投稿記事 by softya(ソフト屋) » 12年前

試せばすぐに分かるはずでよ。まず試してみてください。
どちらかというと送信側のほうが不安です。

ただ、、WSACleanup()だけはどうみてもバグなので直しておいたほうが無難です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

トントン
記事: 100
登録日時: 13年前

Re: webサーバにファイルをPOSTする方法。

#81

投稿記事 by トントン » 12年前

現在のソースでは、受信したファイル名では保存できません。
Perlのopen関数には読み取り用、書き込み用等(他)の引数も合わせて書かなくてはいけません。

コード:

open (OUT,'>',$filename)
ただ、現在のよくわからない状態で上記に修正して公開しようとするのであれば、絶対に止めてください。
ローカル鯖で実施してください。
悪意のあるユーザの標的にされる可能性もあります。
helloworld1853 さんが書きました:まだテスト段階なのでまだそこまでの精度を要求していませんのでエラー処理はここら辺にします。

さてちょっとした問題が発生しました。

どうやらファイル名も渡す必要があるようです。

(拡張子が*.gif *.jpg *.bmpなどの拡張子が存在しているのでjpgだけ対応というのはよくよく考えてみるとおかしいですね。)

cgiを作ってみたので見ていただけますか。

送信側がfilenameにファイル名をpostし、

それをcgiが受け取るという形です。

コード:

#!/usr/local/bin/perl
use CGI;
$q = new CGI;
$hex = $q->param('namae');
$filename = $q->param('filename');#ここの箇所を追加しました。
print "Content-type: text/html\n\n";
print "<META http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n";
$bindata = pack("H*",$hex);
open (OUT,&filename);#ここの箇所を変更しました。
binmode(OUT);
print OUT $bindata;
close (OUT);
print 'sucess';
exit;
追記
う~ん、bmpにせよ、jpgにせよ悪意のあるコードというのは
忍ばせることができるのかな。
どちらにせよ現在のcgiのソースで公開は危険な感じがして心配です。

僕も、そこら辺を勉強してみたいですけどね。。。
何か参考になるサイト、または本があれば良いんですけどね。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#82

投稿記事 by みけCAT » 12年前

トントン さんが書きました:現在のソースでは、受信したファイル名では保存できません。
Perlのopen関数には読み取り用、書き込み用等(他)の引数も合わせて書かなくてはいけません。

コード:

open (OUT,'>',$filename)
横槍すみません。

コード:

open(OUT,"> $filename")
との(挙動の)違いは何ですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

トントン
記事: 100
登録日時: 13年前

Re: webサーバにファイルをPOSTする方法。

#83

投稿記事 by トントン » 12年前

open関数は、ファイルハンドル、モード、ファイルパス
または、ファイルハンドル、(モード+)ファイルパスを
引数としています。(第4引数まであるらしいが、使ったことがないので良く知らない。)
この場合、安全面を考えると3つの引数を渡してやる方が無難といえます。
たとえば、下記のようにすると動作が変わります。

コード:

use strict;
use warnings;

my $file = '>hoge.txt';
my $data = "test";
open my $fh, "$file" or die $!;
print {$fh} $data;
close $fh;
# hoge.txtに新規書き込み

コード:

my $file = '>hoge.txt';
my $data = "test";
open my $fh, ">$file" or die $!;
print {$fh} $data;
close $fh;
# hoge.txtに追記書き込み

コード:

my $file = '>hoge.txt';
my $data = "test";
open my $fh, '>', "$file" or die $!;
print {$fh} $data;
close $fh;
# (下記コメント一部編集)
# windowsの場合
#引数の間違いによるError
# 正しくは$file = 'hoge.txt';
# 
# ubuntsの場合
# >hoge.txtに新規書き込み
また、1番目に示した例の
$fileの値を
$file = '|dir'; # |ls
とすると、ファイル一覧が表示されてしまいます。(正しい動作かは作成した人しだい)

以上より、第3引数まで書くのが主流となっています。

追記
と、見直してみたら

コード:

open(OUT,"> $filename")
モードとファイルパスに空白が入っていましたね。
見落としていました。この場合は、挙動に違いはなさそうですね。

さらに追記
上記コードはubuntsでは、全て動作します。

コード:

open(OUT,"> $filename")
のように、モードとファイルパスに空白が挟んでいれば良いのですが
挟んでいない場合、上記例のように「新規/追記」などに挙動が変わってしまいます。
なので、空白を入れるのを忘れていても安全(または、第2引数の「モード」がファイル名の一部だと間違えにくい)
という利点が大きいようです。
みけCAT さんが書きました:
トントン さんが書きました:現在のソースでは、受信したファイル名では保存できません。
Perlのopen関数には読み取り用、書き込み用等(他)の引数も合わせて書かなくてはいけません。

コード:

open (OUT,'>',$filename)
横槍すみません。

コード:

open(OUT,"> $filename")
との(挙動の)違いは何ですか?

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#84

投稿記事 by helloworld1853 » 12年前

送信側を作りました。

動作確認済みです。

エラー処理はこのままでもいいかなと思っています。

(さきにいろんな機能を実装させることが今は重要なので・・・
 また先ほども説明したように機能を実装させる予定なので
 回りくどい変な箇所もあります。
 ファイルのポインタあたりのところです。)

なにか重要な指摘があればお願いします。

修正するもしくはコメントをのせるなりして対応します。

コード:

# pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>

char ConvHex(int bit4)
{

	const char hexTable[] = 
	{ 

		'0', '1', '2', '3', '4', '5', '6', '7',

		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

	};

	return hexTable[bit4];
}
int main(void)
{
	int filenamesize;
	FILE *fpr;
	char *fname_r = "test.jpg";
	char ServerName[] = "s1.muryo.etowns.net";           // 接続先のホスト名
	struct sockaddr_in addr;
	unsigned char buf[1000];
	unsigned char sendbuf[2001];
	char filename[100];
	filenamesize=sprintf(filename,"filename=%s",fname_r);
	PHOSTENT phostent;                          // サーバの情報を指すポインタ
	unsigned long ulIPAddress;// サーバのIPアドレス格納変数
	int  size;
	int  filesize;
	int i;
	int sock;
	int ret;
 WORD wVersionRequested = MAKEWORD(1, 1); 
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2,0), &wsadata);
	int nErrorStatus;

    nErrorStatus = WSAStartup(wVersionRequested, &wsadata);
    if(atexit((void (*)(void))(WSACleanup))){    // 終了時にWinSockのリソースを解放
        printf("atexit(WSACleanup)失敗\n");
        return -1;
    }
    if(nErrorStatus != 0){
        printf("初期化失敗です\n");
        return -1;
    }
    else{
        if(LOBYTE( wsadata.wVersion ) == 1
            && HIBYTE( wsadata.wVersion ) == 1){    // 要求したバージョンと同一か確認
            printf("WinSock初期化成功\n");
        }
        else{
            printf("WinSock初期化失敗です\n");
            return -1;
        }
    }


	sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	if(sock == INVALID_SOCKET)
	{
		printf("ソケット作成失敗です。\n");
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		return -1;
	}

	// サーバのIPアドレス取得
	ulIPAddress = inet_addr(ServerName);        // IPアドレス取得
	// inet_addr()関数が失敗 ServerNameがホスト名であった場合下の処理に入る
	if(ulIPAddress == -1)
	{
		if( (phostent = gethostbyname(ServerName)) != NULL)
		{
			ulIPAddress = *((unsigned long *)(phostent->h_addr));
		}
		else
		{
			printf("ホストアドレス取得失敗です。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			closesocket(sock);                    // ソケットの破棄
			return -1;            
		}
	}



	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = ulIPAddress;
	addr.sin_port = htons(80);
 


	ret = connect( sock, (struct sockaddr *)&addr, sizeof addr );
	if ( ret < 0 ) 
	{
		printf( "HTTPポートが開けません。\n" );
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		closesocket(sock);
		return -1;
	}
 
	fpr = fopen( fname_r,"rb" );
	if( fpr == NULL )
	{
		printf("ファイルが読み込めません。\n");
		printf("エラー%dが発生しました。\n", WSAGetLastError());
		return -1;
	}

	fseek( fpr, 0, SEEK_END );//サイズ特定
 
	filesize = ftell( fpr );//filesizeにサイズを入れる
 
	fseek( fpr, 0, SEEK_SET );//初期化
 
	char body[] = "&namae=";
	char length[100];
	char head[] = "POST /~yamada_mama_papa/test.cgi HTTP/1.0\r\nHost: s1.muryo.etowns.net\r\n";
	sprintf( length, "Content-Length: %d\r\n", 6+filesize*2+filenamesize );
	i = strlen(length);
	length[i+1] = '\0';

	if(send(sock,head,strlen(head),0)== SOCKET_ERROR ||
	   send(sock,length,strlen(length),0)== SOCKET_ERROR ||
	   send(sock,"\r\n",2,0)== SOCKET_ERROR||
	   send(sock,filename,17,0)== SOCKET_ERROR ||
	   send(sock,body,7,0)== SOCKET_ERROR)
	{
        printf("サーバへの送信失敗です\n");
        printf("エラー%dが発生しました\n", WSAGetLastError());
        shutdown(sock, SD_BOTH);                        // 送受信を無効にする
        closesocket(sock);                        // ソケットの破棄
        return -1;
	}

	for(;;)//ループ
	{
		size = fread( buf, sizeof( unsigned char ), 1000, fpr );
		if(size<0)
		{
			printf("ファイルが読み込めません。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			shutdown(sock, SD_BOTH);                        // 送受信を無効にする
			closesocket(sock);                        // ソケットの破棄
			return -1;
		}
		for( i=0; i<size ; i++ )
		{
			sendbuf[i*2] = ConvHex((buf[i]>>4)&0x0f);//16進数文字列
			sendbuf[i*2+1] = ConvHex(buf[i]&0x0f);   //16進数文字列
			printf("%02X",buf[i]);
		}
		if(send(sock,(const char*)sendbuf,size*2,0)== SOCKET_ERROR)
		{
			printf("サーバへの送信失敗です。\n");
			printf("エラー%dが発生しました。\n", WSAGetLastError());
			shutdown(sock, SD_BOTH);                        // 送受信を無効にする
			closesocket(sock);                        // ソケットの破棄
			return -1;		
		}
	}

	fclose( fpr );
	shutdown(sock, SD_BOTH);
	closesocket( sock );
	WSACleanup();
	return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#85

投稿記事 by softya(ソフト屋) » 12年前

char body[] = "&namae=";は7バイトなのでは?
6の決め打ちはやめてstrlen()を使ったほうが良いと思います。

[補足]
細かいところをちゃんと組む&エラー処理をするというのは何より自分自身の為なんですよ。
バグを出づらくするとか、問題が起きた時の原因を把握しやすくするとかメリットが沢山あります。

そういう意味でそろそろ細かく関数分けすべき時だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

helloworld1853
記事: 181
登録日時: 12年前

Re: webサーバにファイルをPOSTする方法。

#86

投稿記事 by helloworld1853 » 12年前

>strlen()使うほうがよいと思います。

そうですね。

以後改めます。

>そういう意味でそろそろ細かく関数分けすべき時だと思います。

よいコードを書くためには エラー処理、関数わけするほうがよいということですね。

しかし僕にはまだまだ技術が足りないようです。

目標が達成したので ここらへんで "webサーバにファイルをPOSTする方法。"を終了したいと思います。

いつの日か、"よいコードの書き方"について質問するかもしれないので

そのときにこのソースコードを自分なりに見やすくしたものをのせ、

またご教示させてもらえればうれしいと思っています。

長い間 ありがとうございました。

test123

Re: webサーバにファイルをPOSTする方法。

#87

投稿記事 by test123 » 12年前

cgiのソースとc言語のソースを張った方がいいんでは?

sasin

Re: webサーバにファイルをPOSTする方法。

#88

投稿記事 by sasin » 12年前

C言語自体は動くと思われる。
cgiが配布されてるやつでは、動かないと思われる

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#89

投稿記事 by softya(ソフト屋) » 12年前

test123 さん、sasinさん申し訳ないですが名前を変えて同じよう内容を投稿なさらないで下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sasin

Re: webサーバにファイルをPOSTする方法。

#90

投稿記事 by sasin » 12年前

同じないようではないですが、とりあえずすいま名前がtest123ではおかしいかなと思って変更しただけです

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: webサーバにファイルをPOSTする方法。

#91

投稿記事 by softya(ソフト屋) » 12年前

sasin さんが書きました:同じないようではないですが、とりあえずすいま名前がtest123ではおかしいかなと思って変更しただけです
回答者については、名前を変えたのであれば書き添えてもらえば問題ありません。
無闇に変えると質問者を混乱させる事にしかなりません。よろしくお願いします。

あとこの質問はだいぶ前に終了していますのでhelloworld1853さんが見ている保証はできないのと、その後の質問もされていますのでCGIは既にだいぶ変わっているものと思われます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sasin

Re: webサーバにファイルをPOSTする方法。

#92

投稿記事 by sasin » 12年前

わかりました、これから気を付けます

閉鎖

“C言語何でも質問掲示板” へ戻る