none
Microsoft Translator API のクライアントをC言語で作りたい RRS feed

  • 質問

  • C言語を使って文字を翻訳するクライアントと作っています。ですが、エラーが発生し、なかなかプログラムを作成することができません。

    Microsoft Translator API には、httpリクエストでアクセストークンを取得したいと思っています。現在、トークンを取得するところでつまずいています。

    プログラムのどこが間違っているのか、などを教えてください。コメント”//”は自分のメモ等を書いているため気にしないでください 

    よろしくお願いします。

    ソースコード

    // 課題研究 翻訳プログラム.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
    //
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include"stdafx.h"
    #include <winsock2.h>
    #include <stdlib.h>
    #include <pdh.h>
    #include <conio.h>
    #include <string.h>
    #include <tchar.h>
    #include <stdlib.h>
    #include <pdh.h> // Pdh.Lib
    #include <sys/types.h>
    #include <winsock2.h>
    #include<errno.h>
    #include <string.h>
    #include <ws2tcpip.h>
    #pragma comment(lib, "Ws2_32.lib")
    #define BUF_LEN 1024                      /* バッファのサイズ */
    int main(int argc, char *argv[]) {    /* IP アドレス、ポート番号、ソケット */
     char input[1024], output[1024];
     char destination[] = "127.0.0.1";
     unsigned short port = 80;//
     char httppath[] = "/v2/OAuth2-13/";
     char httphost[] = "https://datamarket.accesscontrol.windows.net";
     int result, dstSocket, read_size,err = 0;          //戻り値 ソケット       
     struct sockaddr_in dstAddr;/* sockaddr_in 構造体 */
     char toSendText[BUF_LEN];/* 各種パラメータ */
     char buf[BUF_LEN];
     struct addrinfo hints, *res;//ipadress 解決
     struct in_addr addr;
      WSADATA data;
     memset(&hints, 0, sizeof(hints));
     hints.ai_family =  PF_UNSPEC; //IPv4
     hints.ai_socktype = SOCK_STREAM; //TCP
     hints.ai_flags = 0;
     hints.ai_protocol = 0;
     WSAStartup(MAKEWORD(2, 0), &data);
     if ((result = getaddrinfo("datamarket.accesscontrol.windows.net", NULL, &hints, &res)) != 0) {  
      printf("エラーが発生しました。 IPアドレスを取得できませんでした。\n"); return 1; 
     }
     addr.S_un = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.S_un;
     sprintf(destination, "%s", inet_ntoa(addr));
     printf("IPアドレス:%s\n", destination);
     // char scope[] = "http ://api.microsofttranslator.com ";
     WSAStartup(MAKEWORD(2, 0), &data);/* Windows 独自の設定 */
     memset(&dstAddr, 0, sizeof(dstAddr));/* sockaddr_in 構造体のセット */
     dstAddr.sin_port = htons(port);
     dstAddr.sin_family = AF_INET;
     dstAddr.sin_addr.s_addr = inet_addr(destination);
     dstSocket = socket(AF_INET, SOCK_STREAM, 0);
      /* ソケット生成 */
     if (dstSocket < 0) {
      
      printf("ソケット生成エラー\n");
     }
     printf("ソケット生成完了\n");
        result = connect(dstSocket, (struct sockaddr *) &dstAddr, sizeof(dstAddr));/* 接続 */
     if (result < 0) {
      perror("");
      printf("%d\n", GetLastError());
      printf("接続に失敗しました\n");
      return 0;
     }
     else { printf("接続を確認\n"); }
     /* HTTP プロトコル生成 & サーバに送信 */
     sprintf(toSendText, "POST %s%s HTTP/1.1 \r\n Host:localhost:80\r\nContent-Length: 11\r\n\n grant_type=client_credentials&client_id=windows123456&client_secret=G/KJAtK0cOcDNM4lRzkQhjTlvu7i5UUVDeUHoPYMSOg= ", httphost, httppath);
     send(dstSocket, toSendText, strlen(toSendText), 0);
     
     printf("%s\n",toSendText);
     // HTTP Body部の作成  
     memset(toSendText, 0, sizeof(toSendText));
     for (int i = 0; i < 11; i++) {
      toSendText[i] = i + 5;
     }
     send(dstSocket, toSendText, 11, 0);
     //Dump HTTP response 
     //printf("%s \n", toSendText);
     printf("サーバーに送信しました\n");
     while (1) {
      memset(buf, 0, sizeof(buf));
      read_size = recv(dstSocket, buf, BUF_LEN, 0);
      if (read_size > 0) { printf("%s", buf); }
      else { break; }
     }
     /* Windows 独自の設定 */
     closesocket(dstSocket);    WSACleanup();
     printf("\n入力\n");
     scanf_s("%s", input);
     printf("%s\n", &output);
     freeaddrinfo(res);
     return 0;
    }

    コマンドプロンプトの画面

    IPアドレス:40.124.13.127
    ソケット生成完了
    No error
    10060
    接続に失敗しました
    続行するには何かキーを押してください . . .

    2017年5月2日 11:20

すべての返信

  • 理由としてはポートに80を指定してますが、httpsのポートは443です。
    あとはdestination[]が固定長配列ですが、そこに配列よりも長い文字列をsprintfしてるのではみ出てるとか。

    POSTしてる中身については
     ・host指定がなぜかホストのアドレスで無くローカルになってる?
     ・ホストへのポスト先も指定がおかしい?
     ・Content-Lengthはbodyの大きさなのに小さすぎる?
     ・bodyに入れるべき内容はgrant_type,scope,client_id,client_secret?
     ・POSTをsendした後に謎の11バイトをsendしてる?
    となっていて色々とおかしいです。

    まずは正しいPOSTの内容を調べて、curlやPowerShellのInvoke-RestMethodなどで本当にそのPOSTを受け付けてくれるかテストした方がいいと思います。
    #Microsoft Translator APIのアクセストークン取得に必要な正しいPOSTの形式は知らないので、正しい内容を質問されても判らないです


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年5月2日 16:38
  • ありがとうございます。

    プログラムを修正してもう一度挑戦しようと思います

    2017年5月3日 0:10
  • adinjjjrjccjs さん、こんにちは
    フォーラム オペレーターの立花楓です。
     
    本件についてその後いかがでしょうか。無事にトークンの取得ができましたでしょうか。
    なにか進展がございましたらこちらのスレッドへご返信いただけますと幸いです。

    また、お寄せいただいた情報が参考になった場合には [回答としてマーク] をお願いいたします。

    よろしくお願いします。


    MSDN/TechNet Community Support 立花楓

    2017年5月23日 2:13
    モデレータ