人に聞けない痔の悩み、これでスッキリ >>

お世話になっています。
VC++2005、MFC、Win7、openssl で作業しています。

Gメールから、POP3S 接続でメールを受け取りたいと考えています。
メールヘッダーの受信後に、本文を取り出す前に接続が切れます。

最初に、接続の部分ですが、問題点がありましたら、アドバイスをください。

void CSQMailBoxTreeView::GmailMailDL(){
int nReturnCode;
WSADATA wsaData;
CFileException fileExpection;
#define MAJOR_VERSION_REQUIRED 1
#define MINOR_VERSION_REQUIRED 1

struct sockaddr_in server;


std::string req; // リクエスト
std::string res; // レスポンス
std::string host_url = "pop.googlemail.com";


strcpy_s(gszGmailServerName,(LPCTSTR)oc_Gmailpop3servername);
if(strlen(gszGmailServerName)==0){
MessageBox("設定 - Gmail POP3サーバー から、\n受信メール(POP3)サーバを\n入力して下さい。","POP Server", MB_OK);
}
strcpy_s(gszGmailUserId, (LPCTSTR)oc_Gmailpop3userid);
if(strlen(gszGmailUserId)==0){
MessageBox("設定 - Gmail POP3サーバー から、\nメールサーバのユーザ名を\n入力してください。","POP User ID", MB_OK);
}
strcpy_s(gszGmailPassword, (LPCTSTR)oc_Gmailpop3password);
if(strlen(gszGmailPassword)==0){
MessageBox("設定 - Gmail POP3サーバー から、\nパスワードを入力してください。","警告 PassWord", MB_OK);
}
strcpy_s(gszGmailPOP3Port, (LPCTSTR)oc_Gmailpop3port);
if(strlen(gszGmailPassword)==0){
MessageBox("設定 - Gmail POP3サーバー から、\nポート番号を入力してください。","POP3 PortNumber", MB_OK);
}

// Prepare version for WSAStartup()
WORD wVersionRequired = MAKEWORD(MAJOR_VERSION_REQUIRED, MINOR_VERSION_REQUIRED);
// Initialize the WinSock DLL
nReturnCode = WSAStartup(wVersionRequired, &wsaData);
if (nReturnCode != 0 ){
MessageBox("Error on WSAStartup()","CheckGMail", MB_OK);
return ;
}
// Confirm that the version requested is available.
if (wsaData.wVersion != wVersionRequired){
// Version needed is not available.
MessageBox("Wrong WinSock Version","CheckGMail", MB_OK);
WSACleanup();
return ;
}

sock = socket(AF_INET, SOCK_STREAM, 0);

server.sin_family = AF_INET;
server.sin_port = htons(995);

server.sin_addr.S_un.S_addr = inet_addr(host_url.c_str());
if (server.sin_addr.S_un.S_addr == 0xffffffff) {
struct hostent *host;
unsigned int **addrptr;

host = gethostbyname(host_url.c_str());
if (host == NULL) {
return ;
}

addrptr = (unsigned int **)host->h_addr_list;
while (*addrptr != NULL) {
server.sin_addr.S_un.S_addr = *(*addrptr);
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == 0) {
break;
}
}
if (*addrptr == NULL) {
sprintf_s(outbuf3, "Fatal error: unable to connect to the server.\n");
MessageBox(outbuf3,"Error", MB_OK);
WSACleanup();
return;// -1;
}
}
else {
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) != 0){
return ;
}
}

SSL_load_error_strings();
SSL_library_init();
ctx = SSL_CTX_new(TLSv1_method());
if (ctx == NULL) {
return;// 1;
}

ssl = SSL_new(ctx);
if (ssl == NULL) {
return;// 1;
}

if (SSL_set_fd(ssl, sock) == 0) {
return;// 1;
}

RAND_poll();

while (RAND_status() == 0) {
unsigned short rand_ret = rand() % 65536;
RAND_seed(&rand_ret, sizeof(rand_ret));
}

int ev = SSL_connect(ssl);
if ( ev != 1) {
int ret = SSL_get_error(ssl, ev);
if(ret <= 0){
ERR_print_errors_fp(stderr);
return;// 1;
}
}

if (WSAAsyncSelect(sock, *this, SM_GASYNC3,
FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE) == SOCKET_ERROR){
MessageBox("WSAAsyncSelect() failed","Error", MB_OK);
closesocket(sock);
sock = INVALID_SOCKET;
return;
}

gnAppState = STATE_CONNECTING;
}

このQ&Aに関連する最新のQ&A

A 回答 (2件)

RETRコマンドで読み取り完了したら、そのメールを削除して、QUITコマンドで切断していますから1通しか読み込めないのは想定内の動作のハズですけど、そこらヘンはどうなんですかね?



CSQMailBoxTreeView::GmailProcessData()の呼び出し方次第ではココも正常動作が期待できませんが…。

前回の回答でも指摘しましたが普通のPOP3で正しく動作するもの作ってからの方がいいと思われますが…。
その際、LAN内の別マシンにPOP3サーバを構築すればWireSharkなどでパケットの内容は確認できますし。
# GmailのPOP3って…bad commandで切断されるのね……

あと…MessageBox()でもろもろの通知を出すと「そこで処理が止まる」ので通信扱う場合だと問題が発生することもありますのでご注意を。
# 私ならTRACE()やその類使いますね。(Win32SDKなんでOutputDebugString()ですが…)

この回答への補足

関連する残りの部分です。

POP3 では、メールは取り出せます。
新しく、POP3S で接続しようとしています。

ご指摘の部分を参考に、デバッグを続けます。
ありがとうございました。

// MailAsync(); corresponding to the message SM_GASYNC3.
LRESULT CSQMailBoxTreeView::GmailMailAsync(WPARAM , LPARAM lParam)
{
int GmailnBytesRead;
char buf1[256];

int nEvent = (int)WSAGETSELECTEVENT(lParam);
int nError = (int)WSAGETSELECTERROR(lParam);
sprintf_s(buf1,"hasm %d error\r\n",nError);
if( nError ){
MessageBox(buf1,"Error", MB_OK);
}

switch(nEvent){
case FD_CONNECT:
break;
case FD_WRITE:
break;
case FD_READ:
// Receive waiting data
GmailnBytesRead = SSL_read(
ssl, // socket
gbufRecv, // buffer
sizeof(gbufRecv)-1 // max len to read //はみだしそう -1 付けた
);// recv flags
// Check recv() return code
if (GmailnBytesRead == 0){
// Connection has been closed.
int erv = SSL_get_error(ssl, GmailnBytesRead);
if(erv <= 0){
MessageBox("Connection closed unexpectedly",
"recv() error", MB_OK);
}
break;
}
if (GmailnBytesRead < 0){
int erv = SSL_get_error(ssl, GmailnBytesRead);
if(erv <= 0){
wsprintf((LPSTR)gszTemp,
(LPSTR)"recv() error: %d", GmailnBytesRead);
MessageBox(gszTemp,"recv() error",MB_OK);
gszTemp[0] = '\0';
}
break;
}
// Null terminate the buffer
gbufRecv[GmailnBytesRead] = '\0'; //はみだしそう

// And pass it to be interpreted
GmailProcessData(gbufRecv, GmailnBytesRead);
break;
case FD_CLOSE:
break;
}
fRet = TRUE;
return 0;
}


LPSTR CSQMailBoxTreeView::GmailDecodeError(int ErrorCode)
{
static char Message[1024];

FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)Message, 1024, NULL);
return Message;
}

void CSQMailBoxTreeView::GmailMailDL2(){
reached = download = 0;
in_header = 1;
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("メール受信中です、しばらくお待ちください。");
GmailMailDL();
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("終了。");
}

補足日時:2013/07/31 06:15
    • good
    • 0

>メールヘッダーの受信後に、本文を取り出す前に接続が切れます。



POP3Sで接続して、RETRコマンドの発行まで出来ているんでしょう?
であれば、接続の時のコードを掲示してもあまり意味が無いと思いますが。
# SSL接続の方法などについて意味があるかも知れませんけど、ログイン出来ているならSSL接続は出来ていることになりませんか?

実際のデータ受信処理の辺りがどうなっているのか?
が問題かと思いますが……。
LISTコマンドやTOPコマンド、RETRコマンドは1行受信して終了ではなく、
"."のみの行を受信するまで続きますがそこらヘン正しく処理していますか?
# "\r\n.\r\n"が正確なとこですかねぇ。


POP3Sが~ではなく通常のPOP3でちゃんと処理できるかどうかを先にやってはどうですか?
自由に使えるメールサーバがあれば、こういう時は楽…なんですけどね。
実行しているWindowsに一時的にメールサーバ構築する。なんてのもアリでしょう。
「Windows メールサーバ」辺りで検索すると情報も見つかるでしょう。
# 私はMercury辺りを使ったことがありますが。
# 今はLAN内のメールサーバ(Linux+Dovecot)があるので使っていませんけど。

この回答への補足

void CSQMailBoxTreeView::GmailProcessLine(LPSTR lpStr)
{
int nRet, ret;
long lCount;
long lSize;
CFileStatus fs;
CString sbuf;
BStringBuffer s("");
CSQMailBoxDoc* pDoc = GetDocument();


if(strlen(lpStr)==1 && in_header){
pDoc->GetHeaderInfor();
in_header = 0;
}

// Check response for error
if ((lpStr[0] == '-') && (lpStr[1] == 'E') && (lpStr[2] == 'R') && (lpStr[3] == 'R'))
{
//MessageBox("Negative response: ","Error",MB_OK);
switch(gnAppState)
{
case STATE_CONNECTING:
MessageBox("Connection denied","Error",MB_OK);
break;
case STATE_USER:
MessageBox("Unknown UserID\r\n","Error",MB_OK);
break;
case STATE_PASS:
MessageBox("Wrong Password","Error",MB_OK);
break;
case STATE_STAT:
MessageBox("STAT command not supported","Error",MB_OK);
break;
case STATE_LIST:
state = -STATE_LIST;
MessageBox("メールはありません。");
break;
case STATE_RETR:
state = -STATE_RETR;
MessageBox("Negative RETR response.");
break;
case STATE_QUIT:
MessageBox("QUIT command not supported","Error",MB_OK);
break;
}
wsprintf(gszTemp, "QUIT\r\n");
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_QUIT;

SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
ERR_free_strings();
CloseSocket(sock);

return;
}

// We have a positive response
switch(gnAppState)
{
case STATE_CONNECTING:
// Send the USER portion of the login request and set the app state
wsprintf(gszTemp, "USER %s\r\n", gszGmailUserId);
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_USER;
break;

case STATE_USER:
// Send the PASSword portion of the login request and set the app state
wsprintf(gszTemp, "PASS %s\r\n", gszGmailPassword);
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_PASS;
break;

case STATE_PASS:
// Send the STAT command request and set the app state
wsprintf(gszTemp, "STAT\r\n");
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flagsgs
gnAppState = STATE_STAT;
break;

case STATE_STAT:
// Read the STAT response and print the results
sscanf(lpStr, "%s %ld %ld",
gszTemp, &lCount, &lSize);
if(download == 0){reached = lCount;}
download += 1;
wsprintf(gszTemp, "LIST %d\r\n",download);
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_LIST;
break;

case STATE_LIST:
sscanf(lpStr, "%s %ld %ld",
gszTemp, &lCount, &lSize);
_itoa(lSize, c_strSize,10);
wsprintf(gszTemp, "RETR %d\r\n",download);
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_RETR;
break;

補足日時:2013/07/30 22:28
    • good
    • 0
この回答へのお礼

続きです。(一部重複)接続できていて不安定ですが一度だけメール本文も取得できました。

case STATE_LIST:
sscanf(lpStr, "%s %ld %ld",
gszTemp, &lCount, &lSize);
_itoa(lSize, c_strSize,10);
wsprintf(gszTemp, "RETR %d\r\n",download);
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_RETR;
break;

case STATE_RETR:
if((lpStr[0]=='.') && (strlen(lpStr)==2)){

pDoc->D_hi.DoIt(pDoc->Mailstrs);
strcpy_s(c_strTo, pDoc->D_hi.GetTo());
strcpy_s(c_strSubject, pDoc->D_hi.GetSubject());
strcpy_s(c_strFrom, pDoc->D_hi.GetFrom());
strcpy_s(c_strAttach, "");
//strcpy(c_strSize, "");
strcpy_s(c_strPriority, "2");
strcpy_s(c_strRead, "1");//未読1 , 既読0
if(mailfilter == 1){
ret = pDoc->GetPrgbyAddr(c_strFrom);
if(ret == 0){
strcpy_s(c_strState, "3");//1:受信箱 2:送信済み 3:迷惑メール 4:ゴミ箱
}else{
strcpy_s(c_strState, "1");//1:受信箱 2:送信済み 3:迷惑メール 4:ゴミ箱
}
}else{
strcpy_s(c_strState, "1");//1:受信箱 2:送信済み 3:迷惑メール 4:ゴミ箱
}
strcpy_s(c_strDate, pDoc->D_hi.GetDate());
if(CFile::GetStatus("test2.bin", fs) == TRUE){CFile::Remove("test2.bin");}
u_CStringArray2File("test2.bin", pDoc->Mailstrs);
pDoc->AddNewMail("test2.bin");
pDoc->Mailstrs.RemoveAll();

// Send the QUIT command. And set the app state.
if(0 == atoi(oc_Gmailradio)){
wsprintf(gszTemp, "DELE %d\r\n",download);
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
}
wsprintf(gszTemp, "QUIT\r\n");
nRet = SSL_write(ssl, // socket
gszTemp, // data buffer
strlen(gszTemp)// length of data
);// send flags
gnAppState = STATE_QUIT;
}
else{// by uyama
sbuf = lpStr;
sbuf += "\n";
pDoc->Mailstrs.Add(sbuf);//lpSt + "\n";
}
break;

case STATE_QUIT:

SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
ERR_free_strings();

CloseSocket(sock);

if((state == -STATE_LIST ) || (state == -STATE_RETR)){

}else{
pDoc->m_pTreeView->nImageID = 1;
if(reached == download){
pDoc->m_pListView->ShowReceived();
}
if(reached>download){
in_header = 1;
pDoc->Mailstrs.RemoveAll();
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("メール受信中です、しばらくお待ちください。");
GmailMailDL();
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("終了。");
}
}
}
}



void CSQMailBoxTreeView::GmailProcessData(LPSTR lpBuf, int nBytesRead)
{
static char szResponse[4096];
static int nLen = 0;
char *cp;

// Is there enough room in our buffer for the new data?
if ((nLen + nBytesRead) > sizeof(szResponse)){
MessageBox("Buffer overrun, data truncated","Error",MB_OK);
nLen = 0;
szResponse[0] = '\0';
return;
}
// Append the new data to our buffer
strcat_s(szResponse, sizeof(szResponse), lpBuf);
nLen = strlen(szResponse);

// Process all full lines
while(1){
// Does the buffer contain a full line?
cp = strchr(szResponse, '\n');
if (cp == NULL)
break;
// We have a CR/LF pair
// Replace the LF with a NULL
*cp = '\0';
// And pass it to the ProcesLine() function
GmailProcessLine( szResponse);

// Move the remaining data to the front
// of the buffer
cp++;
if (strlen(cp))
memmove(szResponse, cp, strlen(cp)+1);
else
szResponse[0] = '\0';
}

}

お礼日時:2013/07/30 22:31

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC言語で文字列をかえす正しい書き方が知りたいです?

C言語で次の警告が表示されます。
文字列を返したいのですが、正しい書き方はどのようにすれば良いのでしょうか?


jci.h(20) : warning C4172; ローカル変数またはテンポラリのアドレスを返します。


char *test(char *a, int b)
{
char str[BUFSIZ];
return str; <------

}

Aベストアンサー

再入可能にするかどうかで、回答は変わります。

A.2度呼び出した場合に前のデータを破壊してもよいケース(再入不可能)

char *test(...)
{
static char str[BUFSIZ]; // static指定でメモリは静的に確保されます。

...

return str;
}

B.2度呼び出した場合に前のデータを破壊しないケース(再入可能)
B-1.mallocを使ってもいいケース
char *test(...)
{
char *str;
str = malloc(BUFSIZ);
if(str == NULL) return NULL; // エラー

...

return str;
}
この場合は、呼び出し元でちゃんとfreeしましょう。

B-2.呼び出し元でメモリを確保するケース
(注意:同じアドレスを指定して複数回呼び出すと、メモリ内容は当然破壊されます)
char *test(char *str, ...)
{

...

return str;
}
これは#1の方の回答と同じです。

B-3.B-1/B-2の複合
(注意:NULL以外の同じアドレスを指定して複数回呼び出すと、メモリ内容は当然破壊されます)
char *test(char *str, ...)
{
if(str == NULL)
{
str = malloc(BUFSIZ);
if(str == NULL) return NULL; //エラー
}

...

return str;
}

こんなところですかね。

再入可能にするかどうかで、回答は変わります。

A.2度呼び出した場合に前のデータを破壊してもよいケース(再入不可能)

char *test(...)
{
static char str[BUFSIZ]; // static指定でメモリは静的に確保されます。

...

return str;
}

B.2度呼び出した場合に前のデータを破壊しないケース(再入可能)
B-1.mallocを使ってもいいケース
char *test(...)
{
char *str;
str = malloc(BUFSIZ);
if(str == NULL) return NULL; // エラー

...

return str;
}
この場合は、呼び...続きを読む

Qsocket: recvはいつ,どれだけ受け取るのか?

 現在,参考書にしたがってC++でソケットプログラミングを書いています.

 sendとrecvを非同期にするために,本では select関数やWSAAsyncSelect関数などを利用していて,実際,本のとおりに書いて上手く動いています.

 ここで伺いたいのですが,recvは,どうやって「データが届いたか」を知るのでしょうか.

 同期ならば,トランシーバでの会話のように送信側が「どうぞ」といって送受信を交代させることができますが,非同期ならばそれができません.

 NICとかが,プログラムに「届いたぞ!( or これから届くぞ!)」と教えてくれるのでしょうか.あるいは逆に,プログラムがNICに「届いてる?」と聞いているのでしょうか.仮に,ここに書いたような方法で届いたことが分かったとしても,どれくらい受け取ればいいかは分かりません(それも併せて教えてもらっているのでしょうか.データを送るときには,どれだけ送ればいいか分かりますよね.受信するときはどうしてるのかを知りたいと思っています).

Aベストアンサー

Linux しか知らないので Linux で説明をします。

NIC が通信パケットを受け取ると割り込みが発生し、CPU は割り込みを受け付けて、対応するデバイスドライバを起動します。この時、ドライバはソケットバッファと呼ばれる構造体にパケットの中身をコピーして、Linux カーネルの本体に渡し、そこで TCP 等の上位プロトコル処理が行われます。

一方、ユーザプログラムの方は、 select() なり read() で待っている訳ですが、OS はもちろんプロセスが何を待っているかを知っているので、対応する待ちの条件が満たされると、この場合は select() や read() が、抜けてくる(return する)訳です。

という事で、ユーザのプログラムは select() なり read() なりで受信データを「待つ」ことが必要です。もちろん select() や read() が呼ばれた時点で既に受信しているのならば、それらは直ぐに帰ってきます。read() や recv() はデータが届いた事を知る、というよりは、届いているかチェックして、まだ届いていなければ届くまで待つ(read() が抜けてこない)という処理になります。また NIC とユーザプログラムが直接やり取りをするのではなく、間にバッファがあって、対応するソケットのデータがある(受信済み)/ないか(未受信)、という問い合わせを行っているだけです。

ソケットの場合、データの送受信は非同期であり、送受信のタイミングのずれは(ソケット)バッファである程度吸収されます。もちろん、送受信バッファが満杯になった場合は流量制御が働いて、結果的に送信側の write() や send() が待ちに入ることになります。

Linux (Unix) のソケットの受信では、read() 等で指定されたバッファが常に満杯で返されるとは限らない設計になっています。つまり、その時に受信しているデータを返すだけなので、read() で返されたバイト数を必ず見ないと間違った動きになるので注意してください。

Linux しか知らないので Linux で説明をします。

NIC が通信パケットを受け取ると割り込みが発生し、CPU は割り込みを受け付けて、対応するデバイスドライバを起動します。この時、ドライバはソケットバッファと呼ばれる構造体にパケットの中身をコピーして、Linux カーネルの本体に渡し、そこで TCP 等の上位プロトコル処理が行われます。

一方、ユーザプログラムの方は、 select() なり read() で待っている訳ですが、OS はもちろんプロセスが何を待っているかを知っているので、対応する待ちの条件が満...続きを読む

Qソケットのrecvの戻り値が0

linuxにてソケットの勉強をしようと思い、
簡単なソケット通信のプログラムをCで組みました。

ret = recv(ID, Buff, sizeof(Buff), 0);

といった感じでサーバ側を組んだのですが、
この戻り値retに0が入ることがあり、思うように動いてくれません。

私の認識だと、recvは受信するまで待ち、
受信したサイズを返すと思っているのですが、
それが0とは、いったいどういう意味を持つのでしょうか?

Aベストアンサー

recv()の切断時の返り値は-1とは限りません。
むしろ、通常の切断では0以上が返ると思ってください。
つまり、recv()の返り値だけで切断を検出することは出来ません。

単純に1回の接続で短いデータを1回受信するだけのような場合はrecv()が返ってきた時点で切断されていると見なすことは出来るでしょう。

通常は、プロトコルで切断手順を定めて、切断することがプログラムで分かるよう工夫します。
例えば、終了時には必ず"EOF"という行を送るようにする、等です。

しかし、クライアントが強制終了した場合などは上記方法では対応できないので、alarm()を用いて一定時間通信がなければ自動終了するようにするなどしてタイムアウトを定めるわけです。
もちろん、可能ならばクライアント側で強制終了時もシグナルを拾って切断手順を実行できるようにすることも大事です。

QSSLをC言語でプログラミング

C言語を用いてSSLを実装するプログラムを
作りたいと思っていますが、行き詰まっています。

わかる方いたらよろしくお願いします。
OSはWindows2000で動かしたいと思っています。

Aベストアンサー

SSLのロジックを個人で書くのですか?
通常はNo.1の方もおっしゃるようにOpenSSLなどのフリーのライブラリを用いるか、RSA社などが発売しているライブラリを利用します。

大きな企業で自社内で開発しているところもありますが、研究開発部門で作成され、ソースなど内部は全て社外秘となっています。

参考URL:http://www.rsasecurity.co.jp

QC言語でBASE64のエンコードのプログラミング

現在、C言語(OS:Linux)でSMTPのメールを送るプログラムを作っています。
しかし、送信のところまでは完成したのですが、日本語では送れません。
そこでContent-transfer-encodingをBase64にしようと考えています。
インターネットや本でいろいろ調べましたが、VCでのソースしか載っていなくて、
それを改良しても出来ない状況が続いています。
BASE64については理解していますが、プログラムが組めません。

どなたか、C言語(VCではないもの)でBASE64のエンコードのプログラミングのソースを
公開しているサイトを知りませんか。
また、ソースを公開してくれる人がいましたら、教えてください。
よろしくお願いします。

Aベストアンサー

ここかな?
http://www.kumei.ne.jp/c_lang/sdk3/sdk_235.htm

見ながら作りました。

参考URL:http://www.kumei.ne.jp/c_lang/sdk3/sdk_235.htm

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

Qsleep()関数について

"数秒おきに警報をn回鳴らすプログラム"をC言語で作成しようと
考えています。

プログラム実行環境はWindowsですが、
sleep()関数は使用できないのでしょうか??

仮に使用できない場合、この関数に代わる関数や代替方法が
あれば教えて頂けませんでしょうか? 宜しくお願いします。

Aベストアンサー

正確な動作でも構わなければ
windows.hをインクルードして
Sleep()関数を使いましょう.
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200207/02070061.txt

しかし,正確に数秒おきに動作を行いたい場合はマルチメディアタイマ等を使いましょう.
マルチメディアタイマはミリ秒間隔でコールバック関数を呼び出すことができます.
timeSetEventを用いてコールバック関数の登録を行うことができます.
timeKillEventでコールバック関数の解除を行うことができます.

多分他にも方法があると思うのですが…私はこれぐらいしか知りません^^;

参考URL:http://www.katto.comm.waseda.ac.jp/~katto/Class/GazoTokuron/code/time.html

Q戻り値で構造体を返すことは可能でしょうか?

perlでは以下のように2つの戻り値が可能ですが、C言語では
それができるのでしょうか?
my (ret1, ret2) = test1();

よくやるのは、引数にポインタを渡して、内容を書き換える手を使っていますが、戻り値を複数返せたら、直感的にわかりやすいかなと思いまして・・・

Aベストアンサー

C言語から遠く離れた者ですが、

>>> よくやるのは、引数にポインタを渡して、内容を書き換える手を使っています

これが常識でしょう。これが直感的に理解できるようにC言語を身に付ける必要があるのではないでしょうか。

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む


人気Q&Aランキング