ページ 1 / 1
TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月21日(土) 22:00
by helloworld1853
TCPでチャットプログラムを作っています。
送信と受信を交互にやるために
ソケットを切断しなければいけないようですが、
タイミングがよくわからないので
ここのサイトを参考に
http://intuniv.cs.shinshu-u.ac.jp/Lectu ... ample.html
作っています。
サーバ、クライアントの順に
コンパイルし、実行したところ、
"recv_error :10038"と表示されます。
"ソケット以外のものに対して操作を実行しようとしました。"
という意味らしいです。
原因は何でしょう。
サーバプログラム
コード:
#pragma comment(lib, "wsock32.lib")
#include <stdio.h>
#include <winsock2.h>
#define PORT 80
#define BUFF_SIZE 1024
int crypt(char buff[BUFF_SIZE])
{
int key = 1853;
size_t i;
for(i=0;i<strlen(buff);i++)
{
buff[i] ^= key;
}
return 0;
}
int main(void)
{
WSADATA wsaData;
SOCKET setting_socket, next_socket;
struct sockaddr_in addr;
struct sockaddr_in client;
int len;
//char sendbuff[BUFF_SIZE];
char recvbuff[BUFF_SIZE];
WSAStartup(MAKEWORD(2,0), &wsaData);
setting_socket = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
bind(setting_socket, (struct sockaddr *)&addr, sizeof(addr));
listen(setting_socket, SOMAXCONN);
len = sizeof(client);
while(1)
{
if(next_socket = accept(setting_socket, (struct sockaddr *)&client, &len)<0)
{
printf("accept_error : %d\n", WSAGetLastError());
break;
}
memset(recvbuff, 0, BUFF_SIZE);
while(1)
{
len = recv(next_socket, recvbuff, BUFF_SIZE, 0);
if(len == SOCKET_ERROR)
{
printf("recv_error : %d\n", WSAGetLastError());
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return -1;
}
puts("recv_success");
recvbuff[len] = '\0';
crypt(recvbuff);
if(strcmp(recvbuff,"exit")==0)
{
break;
}
else
{
printf("%s\n",recvbuff);
}
crypt(recvbuff);
if(send(next_socket, recvbuff, BUFF_SIZE, 0)==SOCKET_ERROR)
{
printf("send_error : %d\n", WSAGetLastError());
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return -1;
}
}
}
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return 0;
}
クライアントプログラム
コード:
#pragma comment(lib, "wsock32.lib")
#include <stdio.h>
#include <winsock2.h>
#define PORT 80
#define BUFF_SIZE 1024
int crypt(char buff[BUFF_SIZE])
{
int key = 1853;
size_t i;
for(i=0;i<strlen(buff);i++)
{
buff[i] ^= key;
}
return 0;
}
int main(void)
{
WSADATA wsaData;
struct sockaddr_in server;
SOCKET sock;
char command[BUFF_SIZE];
char output[BUFF_SIZE];
WSAStartup(MAKEWORD(2,0), &wsaData);
sock = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
while(1)
{
if(connect(sock, (struct sockaddr *)&server, sizeof(server))<0)
{
printf("connect_error : %d\n", WSAGetLastError());
break;
}
puts("connect_success"); scanf_s("%s",&command);
if(strcmp(command,"exit")==0)
{
return 0;;
}
crypt(command);
if(send(sock,command,sizeof(command),0)==SOCKET_ERROR)
{
printf("send_error : %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
puts("send_success");
int len = recv(sock,output,sizeof(output),0);
if(len == SOCKET_ERROR)
{
printf("recv_error : %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
puts("recv_success");
output[len] = '\0';
crypt(output);
printf("%s\n",output);
}
closesocket(sock);
WSACleanup();
return 0;
}
よろしくお願いします。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月21日(土) 22:05
by みけCAT
コード:
if(next_socket = accept(setting_socket, (struct sockaddr *)&client, &len)<0)
これにより、next_socketにはソケットではなく、
コード:
accept(setting_socket, (struct sockaddr *)&client, &len)<0
の結果の0または1が代入されます。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 00:57
by helloworld1853
みけCATさん ありがとうございます。
見落としていました。
うまく接続ができましたが
今度は送信ができません。
"aaaa"と入力し、
送信すると、
connect_error:10056と出てきました。
"既に接続済みのソケットに対して接続を要求しました。"
という意味のようです。
なので closesocket(next_socket); や closesocket(sock);
などして解決させました。
しかし、なぜかサーバ側にデータが受信されません。
エラーは発生していません。
recv関数が受信されない状態ってたとえばどういう状況があるのですか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 15:03
by softya(ソフト屋)
最新のコードがないと答えられないと思います。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 15:08
by みけCAT
クライアントで、ループに入る前にconnectしてからループに入るべきだと思います。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 18:06
by helloworld1853
softyaさん、みけCATさん ありがとうございます。
最新コードをのせ忘れました。
変更箇所が多いので
ここにアップロードしました。
サーバ側
http://s1.muryo-de.mydns.jp/~yamada_mam ... server.cpp
クライアント側
http://s1.muryo-de.mydns.jp/~yamada_mam ... client.cpp
みけCATさんのご指摘も改善しました。
実行結果は
クライアント側:
connect_success
test
send_success
サーバ側は:
ready!
でとまってしまいます。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 20:27
by softya(ソフト屋)
ポート80はWEBサーバーで衝突するので変えてあります。
こちらで実行すると
[クライアント]
connect_success
123
send_success
recv_success
123
connect_success
[サーバー]
ready!
recv_success
受信したデータ
復元したデータ 123
accept_error : 10014
となり、最初の通信自体は出来ています。
ただ、サーバー側はソケット閉じているので続けて通信は出来ないと思います。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 21:10
by helloworld1853
softyaさん ありがとうございます。
今 改善してみます。
ところで ブラウザはポート80 を使っているのに
なぜ 複数のサイトにアクセスしても webサーバの衝突が起きないのですか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 21:17
by softya(ソフト屋)
helloworld1853 さんが書きました:softyaさん ありがとうございます。
今 改善してみます。
ところで ブラウザはポート80 を使っているのに
なぜ 複数のサイトにアクセスしても webサーバの衝突が起きないのですか。
受付ポート80はサーバ毎に1つだけですね。
返信のソケットポートは違う番号なので問題無いです。
1つのPCに同じポート番号で受信待ちするとマズイです。
※ 私のPCではWEBサーバーが起動中です。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 21:56
by helloworld1853
softyaさん が実行した結果、
最初の通信ができたようですが、
僕のでは最初の通信ですらできません。
ポート番号をほかのやつでも試してみましたがうまくいきません。
環境が原因でしょうか。
(ちなみにサーバ側のソースコードにcrypt関数がないのを修正してコンパイルしました。)
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 22:04
by softya(ソフト屋)
helloworld1853 さんが書きました:softyaさん が実行した結果、
最初の通信ができたようですが、
僕のでは最初の通信ですらできません。
ポート番号をほかのやつでも試してみましたがうまくいきません。
環境が原因でしょうか。
(ちなみにサーバ側のソースコードにcrypt関数がないのを修正してコンパイルしました。)
同じくcrypt関数を追加しています。
最初起動した時にファイアウォールが遮断しましたが解除してあります。
同じ問題は起きていませんか?
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 22:50
by helloworld1853
コントロールパネルにてV2-server.exeに関してのファイアーウォール(ホーム/社内 プライベート)
の解除を確認してみました。今はパブリックまで解除する必要がないと思っているので
パブリックは解除していません。
セキュリティソフトも二年近く使っていません。マルウェアが原因の可能性もあるので
今セキュリティソフトでフルスキャンしています。
実は説明し忘れていましたが
うちはひとつのルータに対して二つのパソコンが接続されています。
一番目の接続には母のパソコンが・・・
二番目には僕のが接続されています。
あと環境はwindows 7 64bitです。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月22日(日) 23:48
by softya(ソフト屋)
とりあえず思いついたのは2台のPCにサーバとクライアントを分けて動かしてWireSharkでパケットをキャプチャして、どういう通信が行われているか確認することです。
これが一番確実なテスト方法です。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月23日(月) 19:11
by helloworld1853
IPアドレスの設定は
"127.0.0.1"
で大丈夫ですか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月23日(月) 19:23
by h2so5
"127.0.0.1"は自分自身へのアドレスです。
PCごとのローカルIPアドレスは別です。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月24日(火) 21:42
by helloworld1853
server側を192.168.1.3 (ipはipconfigでチェックしました。) に設置し、
client側を192.168.1.2 (僕のです。) に設置しました。
両プログラムを実行したところ
実行結果は
クライアント側:
connect_success
test
send_success
サーバ側は:
ready!
でとまってしまいます。
さっきと同じでした。
winsharkで調べて結果を保存したものをアップロードしました。
http://s1.muryo-de.mydns.jp/~yamada_mama_papa/test.pcap
念のため自分のパソコンで海外のサイトの
チャットプログラムを実行してみましたが
結果が何かおかしいです。
あとここのサイトのサンプルプログラムも自分のパソコン内で
実行したところ正常に動きました。
http://www.geekpage.jp/programming/winsock/tcp.php
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月24日(火) 22:09
by softya(ソフト屋)
パケットを見る限りは、サーバーに接続までは終わっています。
ただ、その後の通信パケットがクライアントからサーバーに送られていません。
winsharkのログには無いので実際に何も送信されていない可能性が高いです。
なのでクライントを疑ってみた方が良いかも知れません。
あっ
scanf_s("%s",&command);
はマズイですね。メモリ破壊しています。
元々commandはポインタなので
scanf_s("%s",command);
です。
さらにscanf_sはサイズ指定も必須なので
scanf_s("%s",command,BUFF_SIZE-1);
が正しいと思います。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月24日(火) 23:10
by helloworld1853
softyaさん、ありがとうございます。
無事動作しました。
やはり文字列、ポインタに対しての
理解が浅かったのが原因のような気がします。
あと
puts("connect_success"); scanf_s("%s",&command);
ここの文だけ二つの処理をしてしまうという
可読性の低さもあまりよくなかったなと
いまさらながら気づいています。
以後気をつけます。
最後に
このプログラムのクライアントはexitと
入力されたら停止するのですが、
exitと入力すると、
Run-Time Check Failure #2 - Stack around the variable 'output' was corrupted.
と表示されます。
ちなみにサーバ側はエラーが出ません。
これはどういう意味ですか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月24日(火) 23:15
by helloworld1853
いい忘れてしまいましたが、
サーバ側がソケットを閉じてしまう問題は修正しました。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月25日(水) 00:02
by softya(ソフト屋)
> Run-Time Check Failure #2 - Stack around the variable 'output' was corrupted.
何らかの原因でメモリ破壊が起きています。
もう一度メモリ関係を見なおしたほうが良いでしょうね。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月25日(水) 00:43
by helloworld1853
recv関数の第三引数あたりが
怪しいと思いましたがよくわかりません。
どこが怪しいと思いますか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月25日(水) 01:03
by softya(ソフト屋)
outputが破壊されているのでoutput自身かcommandが怪しいです。
で、outputやcommandのサイズを超えていないかチェックしてみてはどうでしょうか?
ナル文字も含めて最大BUFF_SIZEである必要があります。
あとcryptのxor変換で文字列の途中の文字が途中でナル文字になる可能性があります。
つまりcryptした文字列はstrlenなどが使えないと言うことです。注意して下さい。
全体的に配列、文字列、ポインタの理解不足でバグを招いている部分が多いです。
しっかりと理解をして対処しましよう。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月25日(水) 22:49
by helloworld1853
output[len] = '\0';
を修正しました。
ようやく完成しました。
動作確認済みです。(windows 7 64bit)
皆様ありがとうございました。
クライアントのソースコード
コード:
#pragma comment(lib,"wsock32.lib")
#include <stdio.h>
#include <winsock2.h>
#define PORT 80
#define BUFF_SIZE 1024
int crypt(char buff[BUFF_SIZE])
{
int key = 1853;
size_t i;
size_t buffsize = strlen(buff);
for(i=0;i<buffsize;i++)
{
buff[i] ^= key;
}
return 0;
}
int main(void)
{
WSADATA wsaData;
struct sockaddr_in server;
SOCKET sock;
char command[BUFF_SIZE];
char output[BUFF_SIZE];
WSAStartup(MAKEWORD(2,0), &wsaData);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sock = socket(AF_INET, SOCK_STREAM, 0);
if(connect(sock, (struct sockaddr *)&server, sizeof(server))<0)
{
printf("connect_error : %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
while(1)
{
scanf_s("%s",command,BUFF_SIZE-1);
crypt(command);
if(send(sock,command,sizeof(command),0)==SOCKET_ERROR)
{
printf("send_error : %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
crypt(command);
if(strcmp(command,"exit")==0)
{
closesocket(sock);
WSACleanup();
return 0;
}
int len = recv(sock,output,sizeof(output),0);
if(len == SOCKET_ERROR)
{
printf("recv_error : %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
output[len-1] = '\0';
printf(">%s\n",output);
}
closesocket(sock);
WSACleanup();
return -1;
}
サーバのソースコード
コード:
#pragma comment(lib, "wsock32.lib")
#include <stdio.h>
#include <winsock2.h>
#define PORT 80
#define BUFF_SIZE 1024
int crypt(char buff[BUFF_SIZE])
{
int key = 1853;
size_t i;
for(i=0;i<strlen(buff);i++)
{
buff[i] ^= key;
}
return 0;
}
int main(void)
{
WSADATA wsaData;
SOCKET setting_socket, next_socket;
struct sockaddr_in addr;
struct sockaddr_in client;
int len;
char recvbuff[BUFF_SIZE];
char sendbuff[BUFF_SIZE];
WSAStartup(MAKEWORD(2,0), &wsaData);
setting_socket = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
bind(setting_socket, (struct sockaddr *)&addr, sizeof(addr));
listen(setting_socket, SOMAXCONN);
len = sizeof(client);
next_socket = accept(setting_socket, (struct sockaddr *)&client, &len);
while(1)
{
if(next_socket == INVALID_SOCKET)
{
printf("accept_error : %d\n", WSAGetLastError());
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return -1;
}
len = recv(next_socket, recvbuff, sizeof(recvbuff), 0);
if(len <= 0)
{
printf("recv_error : %d\n", WSAGetLastError());
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return -1;
}
recvbuff[len-1] = '\0';
crypt(recvbuff);
if(strcmp(recvbuff,"exit")==0)
{
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return 0;
}
printf(">%s\n",recvbuff);
scanf_s("%s",sendbuff,BUFF_SIZE-1);
if(send(next_socket, sendbuff, sizeof(sendbuff), 0)==SOCKET_ERROR)
{
printf("send_error : %d\n", WSAGetLastError());
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return -1;
}
}
closesocket(setting_socket);
closesocket(next_socket);
WSACleanup();
return 0;
}
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月25日(水) 23:03
by softya(ソフト屋)
ええと、output[len-1] = '\0';は少々問題です。lenが必ずBUFF_SIZEであることが前提になっていて危険要素ですね。
一回のrecvで全部のパケットを受け取れること前提にプログラムを組んではいけません。
このプログラムを実際インターネット上でBUFF_SIZEを増やしたりして使うと問題がでると思います。
あくまで実用性がない実験的ならものならOKですが。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 00:10
by helloworld1853
これは、lenが0だった場合に
問題が起こるという意味ですか。
あまり知識がないゆえに
想像ができません。
たとえをご教授してください。
(可能であればlenが***のときに+++エラーが起きるというように・・・)
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 10:59
by softya(ソフト屋)
helloworld1853 さんが書きました:これは、lenが0だった場合に
問題が起こるという意味ですか。
あまり知識がないゆえに
想像ができません。
たとえをご教授してください。
(可能であればlenが***のときに+++エラーが起きるというように・・・)
問題点ですが。
・lenが0の時は当然メモリ保護エラーやメモリ破壊が起こるのでダメです。
・必ずlen-1なので実際に送ったデータよりも1バイト小さくしています。偶然今のプログラムはそれで問題がない状態になってますが。
・一回のrecvで全部のパケットが届くことを前提に組んではいけません。
※ 有るサイズを超えるとパケットは分割されて届きます。有るサイズは状況により変わるので実験的な時を除いて分割される前提で組むのが基本です。
・送るデータが実際のデータの長さ関係なしにBUFF_SIZE分送信しているもの無駄だと思います。
ですかね。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 16:36
by helloworld1853
パケットが分割して
送られてきても大丈夫な関数の
ソースコードをお願いします。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 16:39
by softya(ソフト屋)
helloworld1853 さんが書きました:パケットが分割して
送られてきても大丈夫な関数の
ソースコードをお願いします。
ネット上のあっちこっちにありますので、まず探してみて下さい。
簡単に言えばrecvの戻り値が0になるまで繰り返すだけです。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 17:57
by helloworld1853
ところで話が変わりますが、
outputメモリが破壊される
問題はどこのコードが原因ですか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 17:59
by softya(ソフト屋)
helloworld1853 さんが書きました:ところで話が変わりますが、
outputメモリが破壊される
問題はどこのコードが原因ですか。
確認してませんがoutputに書き込む時にchar output[BUFF_SIZE]の後ろに書いているはずです。
確認したのではないですか? していなかったら確認して下さい。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 20:36
by helloworld1853
sendするときに
どんなときでも1024B
送信してしまう問題を解決し忘れていました。
これを解決したら直りました。
あと分割対応recv関数を
作っているのですが、
0になるまでループを続けるということは
sendも繰り返さなくてはならないのですか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 20:42
by softya(ソフト屋)
helloworld1853 さんが書きました:sendするときに
どんなときでも1024B
送信してしまう問題を解決し忘れていました。
これを解決したら直りました。
なんとなく治ったでは理解になりませんので元に戻してオーバーしている事実を確認したほうが良いです。
デバッグは
1)実際の問題点の確認。
2)推測される問題点を修正。
3)治ったことを確認
でちゃんとしたデバッグの完了です。
1)などを手を抜くとろくな事はありません。
helloworld1853 さんが書きました:
あと分割対応recv関数を
作っているのですが、
0になるまでループを続けるということは
sendも繰り返さなくてはならないのですか。
分割は、パソコンのOSやスイッチングハブ、ルータ、モデム、インテーネット経路などの都合で起こりますので送信する側は気にしなくて良いです。
逆に言えば分割したくなくても分割されます。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 21:47
by helloworld1853
1)実際の問題点の確認。
データの大きさが1024だと
メモリ違反を起こしてしまう
原因char output[1024];は
output[0]からoutput[1023]
までしかない。
そこに
output[1024] = '\0';
と代入するとメモリ違反が起きる。
2)推測される問題点を修正。
scanf_sのあとに
strlenでサイズ特定
し、send関数に渡す
1024を越えることがなくなる
3)治ったことを確認
確認しました。
送られてきたデータが
分割されたデータの一部なのか、
それで全部のデータなのか判断する方法はありますか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 21:52
by softya(ソフト屋)
helloworld1853 さんが書きました:1)実際の問題点の確認。
データの大きさが1024だと
メモリ違反を起こしてしまう
原因char output[1024];は
output[0]からoutput[1023]
までしかない。
そこに
output[1024] = '\0';
と代入するとメモリ違反が起きる。
2)推測される問題点を修正。
scanf_sのあとに
strlenでサイズ特定
し、send関数に渡す
1024を越えることがなくなる
3)治ったことを確認
確認しました。
デバッグとは、そういう事です。基本的に怪しい所を闇雲に修正はせず。
間違っていることを確認してから修正して下さい。そうすれば後から変なバグに悩まされずに済みます。
helloworld1853 さんが書きました:
送られてきたデータが
分割されたデータの一部なのか、
それで全部のデータなのか判断する方法はありますか。
無いので通常は送信データ先頭に送信データサイズのデータを付与します。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月26日(木) 23:43
by helloworld1853
http://s1.etowns.server-on.net/~yamada_ ... client.cpp
新しく関数を追加しました。
took_size関数は
先頭にあるサイズデータを
習得します。
先頭には
"0000012345"
というように10進数で
10文字数字が入っています。
これを数値に変えるのが
took_size関数です。
正直自信がないので見ていただきたいです。
あと未完成ながらも
my_recv関数も追加しました。
引数はrecv関数と同じで、
分割されたデータに対応できます。
こちらも見ていただけると幸いです。
ソースコードが汚いですが、
よろしくお願いします。
http://s1.etowns.server-on.net/~yamada_ ... client.cpp
ここにアップロードしました。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月27日(金) 00:19
by softya(ソフト屋)
すいません。今日は見れません。
明日また見ますので。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月27日(金) 00:56
by helloworld1853
すみません。
コメント入れ忘れていましたし、
ソースもぐちゃぐちゃでした。
今改善したので
お願いします。
では また 明日。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月27日(金) 11:37
by softya(ソフト屋)
見ましたので問題点を書きます。
ポインタ・配列理解や文字列の扱いなどにかなり不安を感じます。
1.1回目のrecvでエラー処理がありません。
2.if(output == tooksize)
outputがバッファのoutputと名前がかぶって分かりづらいです。
lenとかサイズを表す名称を何処かに入れて下さい。
3.my_recv関数内においてrecvbuffとbuffの扱いに混乱が見受けられます。
recvlen=recv(sock,recvbuff,size,flag);
recv関数でrecvbuffのサイズがなぜbuffのsizeなのでしょうか?全部がBUFF_SIZE前提の設計はマズイです。
4.上と同様ですが
strcat(buff,recvbuff);
のあと
recvbuff[tooksize]='\0';
は手遅れです。
5.2回目のrecvからcryptがなくなっています。
6.if(len>size || len == tooksize)の時に
strcat(buff,recvbuff);
が無いのでバッファがコピーされません。
それとlen>sizeの時はエラー表示したほうが良いと思います。
ここからはtook_size専用です。
T1.took_sizeの戻り値が-1の時の処理がありません。
T2. number = buff;だと0サプレスにはなりません。それよりも危険なことが起こります。
000の時の動作をデバッガで確認してみて下さい。
T3. if(buff=='0' && check==0)//余計な部分だった場合
コレは連続する0には対処できていません。
T4. size = (int)( number - '0' );
ポインタ値から文字'0'を引いても不思議な値しか求まりません。
文字型の数値からint型への変換が根本的に間違っています。
実は便利な関数もありますが、ここはあえて自力で数値型に変換してみて下さい。
ヒントは各桁は10倍づつである。って事です。
ちなみに、BUFF_SIZEを8192とか16384とかにすればローカルでも分割をテストできるはずです。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月28日(土) 00:04
by helloworld1853
データの先頭からデータサイズを受け取る
関数を新しく作り直しました。
やはり眠い状態で作った昨日の関数とは
質が違います。
テスト済みで、我ながらよくやったと思っています。
ところでchar型において
0,1,2,3,4,5,
という数字は
16進数で
0x30,0x31,0x32,0x33,0x34,0x35
ですか。
コード:
#include <stdio.h>
#include <string.h>
#define BUFF_SIZE 1024
int TAKE_SIZE_FROM_DATA(char data[BUFF_SIZE])
{
char real_data[11];
int counter_for_data=0;
int counter_for_real_data=0;
int i;
while(counter_for_data<10)
{
if(data[counter_for_data] != '0')
{
break;
}
counter_for_data += 1;
}
i = 10-counter_for_data;
for(; counter_for_real_data<i; ++counter_for_data, ++counter_for_real_data)
{
real_data[counter_for_real_data] = data[counter_for_data];
}
real_data[counter_for_real_data] = '\0';
printf("%s",real_data);
return 0;
}
int main(void)
{
char buff[BUFF_SIZE];
scanf("%s", buff);
int size = strlen(buff);
buff[size] = '\0';
TAKE_SIZE_FROM_DATA(buff);
return 0;
}
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月28日(土) 17:10
by helloworld1853
>ヒントは各桁は10倍づつである。って事です。
の意味がようやくわかりました。
前のコメントは無視してください。
あとこれも今気づいたのですが、
変数が 例えば001でも1でもプログラムには影響がないのでしょうか。
001 を二進数にすると
0000・・・0001 で、
1も
0000・・・0001
で同じなので・・・
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月28日(土) 17:19
by softya(ソフト屋)
001と1とソースコードに書いたら同じです。010と10は実は違います。0から始まるのは8進法だからです。
文字列の数値をどう解釈するかはプログラムを作る人のさじ加減次第です。
回答を忘れていてました。申し訳ないです。
TAKE_SIZE_FROM_DATAの処理は合っていると思いますが非常に読み辛いコードですね。
iは止めましょう。
こういう処理をゼロ・サプレス処理といいます。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月29日(日) 00:06
by helloworld1853
sprintf(sendbuff,"%10.d%s",size += 10, command);
とすると、sendbuffには
" 14test"
と代入されます。
"000014test"
のように代入されてほしかったのですが、
なぜ空白なのでしょうか。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月29日(日) 00:26
by softya(ソフト屋)
helloworld1853 さんが書きました:sprintf(sendbuff,"%10.d%s",size += 10, command);
とすると、sendbuffには
" 14test"
と代入されます。
"000014test"
のように代入されてほしかったのですが、
なぜ空白なのでしょうか。
%010dをお試しください。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月31日(火) 18:01
by helloworld1853
softyaさんありがとうございます。
http://s1.etowns.server-on.net/~yamada_ ... client.cpp
http://s1.etowns.server-on.net/~yamada_ ... server.cpp
完成しました。
動作確認しました。
ソースコードが汚い以外に
問題点はないと思います。
きれいなソースコードについて質問したいのですが、
新しくトピックをたてたほうがいいでしょうか。(深い内容になりそうなので、)
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月31日(火) 18:04
by softya(ソフト屋)
おめでとうございます。
そうですね別トピックが良いと思います。
Re: TCPにおいてエラー10038が発生してしまう。
Posted: 2012年7月31日(火) 18:31
by helloworld1853
ありがとうございます。
通信系の問題は解決されたので、
ここで終わりにしたいと思います。
しかし、"ソースコードの美しさ"について問題が多いので、
http://dixq.net/forum/viewtopic.php?f=3&t=11189
ここにて先ほどのソースコードを
中心に "きれいなソースコードの書き方" について
質問させていただきました。
よろしければこちらもお願いします。
回答してくださった皆様ありがとうございました。