TCPにおいてエラー10038が発生してしまう。

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

TCPにおいてエラー10038が発生してしまう。

#1

投稿記事 by helloworld1853 » 13年前

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;
}
よろしくお願いします。

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

Re: TCPにおいてエラー10038が発生してしまう。

#2

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

コード:

if(next_socket = accept(setting_socket, (struct sockaddr *)&client, &len)<0)
これにより、next_socketにはソケットではなく、

コード:

accept(setting_socket, (struct sockaddr *)&client, &len)<0
の結果の0または1が代入されます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: TCPにおいてエラー10038が発生してしまう。

#3

投稿記事 by helloworld1853 » 13年前

みけCATさん ありがとうございます。

見落としていました。

うまく接続ができましたが

今度は送信ができません。

"aaaa"と入力し、

送信すると、

connect_error:10056と出てきました。

"既に接続済みのソケットに対して接続を要求しました。"

という意味のようです。

なので closesocket(next_socket); や closesocket(sock);

などして解決させました。

しかし、なぜかサーバ側にデータが受信されません。

エラーは発生していません。

recv関数が受信されない状態ってたとえばどういう状況があるのですか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#4

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

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

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

Re: TCPにおいてエラー10038が発生してしまう。

#5

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

クライアントで、ループに入る前にconnectしてからループに入るべきだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: TCPにおいてエラー10038が発生してしまう。

#6

投稿記事 by helloworld1853 » 13年前

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!
でとまってしまいます。

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

Re: TCPにおいてエラー10038が発生してしまう。

#7

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

ポート80はWEBサーバーで衝突するので変えてあります。
こちらで実行すると

[クライアント]
connect_success
123
send_success
recv_success
123
connect_success

[サーバー]
ready!
recv_success
受信したデータ
復元したデータ 123
accept_error : 10014

となり、最初の通信自体は出来ています。
ただ、サーバー側はソケット閉じているので続けて通信は出来ないと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#8

投稿記事 by helloworld1853 » 13年前

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

今 改善してみます。

ところで ブラウザはポート80 を使っているのに

なぜ 複数のサイトにアクセスしても webサーバの衝突が起きないのですか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#9

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

helloworld1853 さんが書きました:softyaさん ありがとうございます。

今 改善してみます。

ところで ブラウザはポート80 を使っているのに

なぜ 複数のサイトにアクセスしても webサーバの衝突が起きないのですか。
受付ポート80はサーバ毎に1つだけですね。
返信のソケットポートは違う番号なので問題無いです。
1つのPCに同じポート番号で受信待ちするとマズイです。

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

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

Re: TCPにおいてエラー10038が発生してしまう。

#10

投稿記事 by helloworld1853 » 13年前

softyaさん が実行した結果、
最初の通信ができたようですが、
僕のでは最初の通信ですらできません。
ポート番号をほかのやつでも試してみましたがうまくいきません。
環境が原因でしょうか。
(ちなみにサーバ側のソースコードにcrypt関数がないのを修正してコンパイルしました。)

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

Re: TCPにおいてエラー10038が発生してしまう。

#11

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

helloworld1853 さんが書きました:softyaさん が実行した結果、
最初の通信ができたようですが、
僕のでは最初の通信ですらできません。
ポート番号をほかのやつでも試してみましたがうまくいきません。
環境が原因でしょうか。
(ちなみにサーバ側のソースコードにcrypt関数がないのを修正してコンパイルしました。)
同じくcrypt関数を追加しています。
最初起動した時にファイアウォールが遮断しましたが解除してあります。
同じ問題は起きていませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#12

投稿記事 by helloworld1853 » 13年前

コントロールパネルにてV2-server.exeに関してのファイアーウォール(ホーム/社内 プライベート)
の解除を確認してみました。今はパブリックまで解除する必要がないと思っているので
パブリックは解除していません。
セキュリティソフトも二年近く使っていません。マルウェアが原因の可能性もあるので
今セキュリティソフトでフルスキャンしています。
実は説明し忘れていましたが
うちはひとつのルータに対して二つのパソコンが接続されています。
一番目の接続には母のパソコンが・・・
二番目には僕のが接続されています。
あと環境はwindows 7 64bitです。

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

Re: TCPにおいてエラー10038が発生してしまう。

#13

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

とりあえず思いついたのは2台のPCにサーバとクライアントを分けて動かしてWireSharkでパケットをキャプチャして、どういう通信が行われているか確認することです。
これが一番確実なテスト方法です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#14

投稿記事 by helloworld1853 » 13年前

IPアドレスの設定は
"127.0.0.1"
で大丈夫ですか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#15

投稿記事 by h2so5 » 13年前

"127.0.0.1"は自分自身へのアドレスです。
PCごとのローカルIPアドレスは別です。

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

Re: TCPにおいてエラー10038が発生してしまう。

#16

投稿記事 by helloworld1853 » 13年前

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

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

Re: TCPにおいてエラー10038が発生してしまう。

#17

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

パケットを見る限りは、サーバーに接続までは終わっています。
ただ、その後の通信パケットがクライアントからサーバーに送られていません。
winsharkのログには無いので実際に何も送信されていない可能性が高いです。
なのでクライントを疑ってみた方が良いかも知れません。

あっ
scanf_s("%s",&command);
はマズイですね。メモリ破壊しています。
元々commandはポインタなので
scanf_s("%s",command);
です。
さらにscanf_sはサイズ指定も必須なので
scanf_s("%s",command,BUFF_SIZE-1);
が正しいと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#18

投稿記事 by helloworld1853 » 13年前

softyaさん、ありがとうございます。
無事動作しました。
やはり文字列、ポインタに対しての
理解が浅かったのが原因のような気がします。
あと
puts("connect_success"); scanf_s("%s",&command);
ここの文だけ二つの処理をしてしまうという
可読性の低さもあまりよくなかったなと
いまさらながら気づいています。
以後気をつけます。

最後に
このプログラムのクライアントはexitと
入力されたら停止するのですが、
exitと入力すると、
Run-Time Check Failure #2 - Stack around the variable 'output' was corrupted.
と表示されます。
ちなみにサーバ側はエラーが出ません。
これはどういう意味ですか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#19

投稿記事 by helloworld1853 » 13年前

いい忘れてしまいましたが、
サーバ側がソケットを閉じてしまう問題は修正しました。

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

Re: TCPにおいてエラー10038が発生してしまう。

#20

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

> Run-Time Check Failure #2 - Stack around the variable 'output' was corrupted.

何らかの原因でメモリ破壊が起きています。
もう一度メモリ関係を見なおしたほうが良いでしょうね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#21

投稿記事 by helloworld1853 » 13年前

recv関数の第三引数あたりが
怪しいと思いましたがよくわかりません。
どこが怪しいと思いますか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#22

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

outputが破壊されているのでoutput自身かcommandが怪しいです。
で、outputやcommandのサイズを超えていないかチェックしてみてはどうでしょうか?
ナル文字も含めて最大BUFF_SIZEである必要があります。

あとcryptのxor変換で文字列の途中の文字が途中でナル文字になる可能性があります。
つまりcryptした文字列はstrlenなどが使えないと言うことです。注意して下さい。

全体的に配列、文字列、ポインタの理解不足でバグを招いている部分が多いです。
しっかりと理解をして対処しましよう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#23

投稿記事 by helloworld1853 » 13年前

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;
}

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

Re: TCPにおいてエラー10038が発生してしまう。

#24

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

ええと、output[len-1] = '\0';は少々問題です。lenが必ずBUFF_SIZEであることが前提になっていて危険要素ですね。
一回のrecvで全部のパケットを受け取れること前提にプログラムを組んではいけません。
このプログラムを実際インターネット上でBUFF_SIZEを増やしたりして使うと問題がでると思います。
あくまで実用性がない実験的ならものならOKですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#25

投稿記事 by helloworld1853 » 13年前

これは、lenが0だった場合に
問題が起こるという意味ですか。
あまり知識がないゆえに
想像ができません。
たとえをご教授してください。
(可能であればlenが***のときに+++エラーが起きるというように・・・)

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

Re: TCPにおいてエラー10038が発生してしまう。

#26

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

helloworld1853 さんが書きました:これは、lenが0だった場合に
問題が起こるという意味ですか。
あまり知識がないゆえに
想像ができません。
たとえをご教授してください。
(可能であればlenが***のときに+++エラーが起きるというように・・・)
問題点ですが。
・lenが0の時は当然メモリ保護エラーやメモリ破壊が起こるのでダメです。
・必ずlen-1なので実際に送ったデータよりも1バイト小さくしています。偶然今のプログラムはそれで問題がない状態になってますが。
・一回のrecvで全部のパケットが届くことを前提に組んではいけません。
※ 有るサイズを超えるとパケットは分割されて届きます。有るサイズは状況により変わるので実験的な時を除いて分割される前提で組むのが基本です。
・送るデータが実際のデータの長さ関係なしにBUFF_SIZE分送信しているもの無駄だと思います。
ですかね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#27

投稿記事 by helloworld1853 » 13年前

パケットが分割して
送られてきても大丈夫な関数の
ソースコードをお願いします。

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

Re: TCPにおいてエラー10038が発生してしまう。

#28

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

helloworld1853 さんが書きました:パケットが分割して
送られてきても大丈夫な関数の
ソースコードをお願いします。
ネット上のあっちこっちにありますので、まず探してみて下さい。
簡単に言えばrecvの戻り値が0になるまで繰り返すだけです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#29

投稿記事 by helloworld1853 » 13年前

ところで話が変わりますが、
outputメモリが破壊される
問題はどこのコードが原因ですか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#30

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

helloworld1853 さんが書きました:ところで話が変わりますが、
outputメモリが破壊される
問題はどこのコードが原因ですか。
確認してませんがoutputに書き込む時にchar output[BUFF_SIZE]の後ろに書いているはずです。
確認したのではないですか? していなかったら確認して下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#31

投稿記事 by helloworld1853 » 13年前

sendするときに
どんなときでも1024B
送信してしまう問題を解決し忘れていました。
これを解決したら直りました。

あと分割対応recv関数を
作っているのですが、
0になるまでループを続けるということは
sendも繰り返さなくてはならないのですか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#32

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

helloworld1853 さんが書きました:sendするときに
どんなときでも1024B
送信してしまう問題を解決し忘れていました。
これを解決したら直りました。
なんとなく治ったでは理解になりませんので元に戻してオーバーしている事実を確認したほうが良いです。
デバッグは
1)実際の問題点の確認。
2)推測される問題点を修正。
3)治ったことを確認
でちゃんとしたデバッグの完了です。
1)などを手を抜くとろくな事はありません。
helloworld1853 さんが書きました: あと分割対応recv関数を
作っているのですが、
0になるまでループを続けるということは
sendも繰り返さなくてはならないのですか。
分割は、パソコンのOSやスイッチングハブ、ルータ、モデム、インテーネット経路などの都合で起こりますので送信する側は気にしなくて良いです。
逆に言えば分割したくなくても分割されます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#33

投稿記事 by helloworld1853 » 13年前

1)実際の問題点の確認。
データの大きさが1024だと
メモリ違反を起こしてしまう
原因char output[1024];は
output[0]からoutput[1023]
までしかない。
そこに
output[1024] = '\0';
と代入するとメモリ違反が起きる。

2)推測される問題点を修正。
scanf_sのあとに
strlenでサイズ特定
し、send関数に渡す
1024を越えることがなくなる

3)治ったことを確認
確認しました。

送られてきたデータが
分割されたデータの一部なのか、
それで全部のデータなのか判断する方法はありますか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#34

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

helloworld1853 さんが書きました:1)実際の問題点の確認。
データの大きさが1024だと
メモリ違反を起こしてしまう
原因char output[1024];は
output[0]からoutput[1023]
までしかない。
そこに
output[1024] = '\0';
と代入するとメモリ違反が起きる。

2)推測される問題点を修正。
scanf_sのあとに
strlenでサイズ特定
し、send関数に渡す
1024を越えることがなくなる

3)治ったことを確認
確認しました。

デバッグとは、そういう事です。基本的に怪しい所を闇雲に修正はせず。
間違っていることを確認してから修正して下さい。そうすれば後から変なバグに悩まされずに済みます。
helloworld1853 さんが書きました: 送られてきたデータが
分割されたデータの一部なのか、
それで全部のデータなのか判断する方法はありますか。
無いので通常は送信データ先頭に送信データサイズのデータを付与します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#35

投稿記事 by helloworld1853 » 13年前

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
ここにアップロードしました。

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

Re: TCPにおいてエラー10038が発生してしまう。

#36

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

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

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

Re: TCPにおいてエラー10038が発生してしまう。

#37

投稿記事 by helloworld1853 » 13年前

すみません。
コメント入れ忘れていましたし、
ソースもぐちゃぐちゃでした。
今改善したので
お願いします。

では また 明日。

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

Re: TCPにおいてエラー10038が発生してしまう。

#38

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

見ましたので問題点を書きます。
ポインタ・配列理解や文字列の扱いなどにかなり不安を感じます。

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とかにすればローカルでも分割をテストできるはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#39

投稿記事 by helloworld1853 » 13年前

データの先頭からデータサイズを受け取る
関数を新しく作り直しました。
やはり眠い状態で作った昨日の関数とは
質が違います。
テスト済みで、我ながらよくやったと思っています。

ところで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;
}

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

Re: TCPにおいてエラー10038が発生してしまう。

#40

投稿記事 by helloworld1853 » 13年前

>ヒントは各桁は10倍づつである。って事です。
の意味がようやくわかりました。
前のコメントは無視してください。
あとこれも今気づいたのですが、
変数が 例えば001でも1でもプログラムには影響がないのでしょうか。
001 を二進数にすると
0000・・・0001 で、
1も
0000・・・0001
で同じなので・・・

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

Re: TCPにおいてエラー10038が発生してしまう。

#41

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

001と1とソースコードに書いたら同じです。010と10は実は違います。0から始まるのは8進法だからです。
文字列の数値をどう解釈するかはプログラムを作る人のさじ加減次第です。

回答を忘れていてました。申し訳ないです。
TAKE_SIZE_FROM_DATAの処理は合っていると思いますが非常に読み辛いコードですね。
iは止めましょう。
こういう処理をゼロ・サプレス処理といいます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#42

投稿記事 by helloworld1853 » 13年前

sprintf(sendbuff,"%10.d%s",size += 10, command);

とすると、sendbuffには
" 14test"
と代入されます。
"000014test"
のように代入されてほしかったのですが、
なぜ空白なのでしょうか。

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

Re: TCPにおいてエラー10038が発生してしまう。

#43

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

helloworld1853 さんが書きました:sprintf(sendbuff,"%10.d%s",size += 10, command);

とすると、sendbuffには
" 14test"
と代入されます。
"000014test"
のように代入されてほしかったのですが、
なぜ空白なのでしょうか。
%010dをお試しください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#44

投稿記事 by helloworld1853 » 13年前

softyaさんありがとうございます。
http://s1.etowns.server-on.net/~yamada_ ... client.cpp
http://s1.etowns.server-on.net/~yamada_ ... server.cpp
完成しました。
動作確認しました。
ソースコードが汚い以外に
問題点はないと思います。
きれいなソースコードについて質問したいのですが、
新しくトピックをたてたほうがいいでしょうか。(深い内容になりそうなので、)

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

Re: TCPにおいてエラー10038が発生してしまう。

#45

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

helloworld1853 さんが書きました:softyaさんありがとうございます。
http://s1.etowns.server-on.net/~yamada_ ... client.cpp
http://s1.etowns.server-on.net/~yamada_ ... server.cpp
完成しました。
動作確認しました。
ソースコードが汚い以外に
問題点はないと思います。
きれいなソースコードについて質問したいのですが、
新しくトピックをたてたほうがいいでしょうか。(深い内容になりそうなので、)
おめでとうございます。
そうですね別トピックが良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: TCPにおいてエラー10038が発生してしまう。

#46

投稿記事 by helloworld1853 » 13年前

ありがとうございます。
通信系の問題は解決されたので、
ここで終わりにしたいと思います。

しかし、"ソースコードの美しさ"について問題が多いので、
http://dixq.net/forum/viewtopic.php?f=3&t=11189
ここにて先ほどのソースコードを
中心に "きれいなソースコードの書き方" について
質問させていただきました。
よろしければこちらもお願いします。

回答してくださった皆様ありがとうございました。

閉鎖

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