質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

4084閲覧

C言語を使ってAPIを叩くプログラムの作成に関して(Windows)

YuuT

総合スコア673

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2019/04/19 08:26

編集2019/04/19 08:29

C言語(コンパイラ型言語)の初心者です。
普段はPythonを使用しているため、わからない点が多く、躓いています。

前提・実現したいこと

現在、C言語でAPIを叩くプログラムを作成しています。
上記のプログラムはWindows上で動作する必要があるので、VisualStudioを使って開発を行い、exeを作成しています。

使用イメージとしては、トークンを取得する際に上記のプログラムを使用します。
特定のURLに対してユーザー名とパスワードを含んだJSONデータをPOST送信し、トークンが含まれたレスポンス(json)を受けるといった形です。

動作環境

Windows 10
Visual Studio 2017

エラーに関して

以下のエラー(レスポンス)が返ってきます。*一部内容を抜いています

HTTP/1.1 400 Bad Request Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Content-Type, Authorization, Accept, key, secret, Usertoken, Appkey, Appsecret, Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Origin: * Access-Control-Max-Age: 1728000 Content-Type: text/plain; charset=utf-8 X-Content-Type-Options: nosniff Date: Fri, 19 Apr 2019 08:08:11 GMT Content-Length: 265 {"error":{"id":"xxxxxx","code":1100,"level":1,"category":"Username","message":"Bad request","detail":"Invalid json in call to authenticate device","lowLevelError":{},"line":"/go/src/api.go:66"},"statusCode":400} HTTP/1.1 400 Bad Request Content-Type: text/plain; charset=utf-8 Connection: close

sendしている内容は以下の通りです。

POST /{path}/auth HTTP/1.1 Host: 192.168.00.10:8080 Content-Type: application/json {"userName":"hoge,"password":"foo"}

現状のコード

現状、以下の様なコードを使用しています。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include "MQTTClient.h" 5#include "cJSON.h" 6#include <winsock2.h> 7 8#define BUF_LEN 4096 9 10int main(int argc, char* argv[]) 11{ 12 // REST API叩く 13 char destination[] = "192.168.00.10"; // 例 14 unsigned short port = 8080; // 例 15 char httppath[] = "/{path}/auth";// 例 16 char httphost[] = "192.168.00.10";// 例 17 int dstSocket; 18 int result; 19 20 /* sockaddr_in 構造体 */ 21 struct sockaddr_in dstAddr; 22 23 /* パラメータ */ 24 char toSendText[BUF_LEN]; 25 char buf[BUF_LEN]; 26 int read_size; 27 28 WSADATA data; 29 WSAStartup(MAKEWORD(2, 0), &data); 30 31 /* sockaddr_in 構造体のセット */ 32 memset(&dstAddr, 0, sizeof(dstAddr)); 33 dstAddr.sin_port = htons(port); 34 dstAddr.sin_family = AF_INET; 35 dstAddr.sin_addr.s_addr = inet_addr(destination); 36 37 /* ソケット生成 */ 38 dstSocket = socket(AF_INET, SOCK_STREAM, 0); 39 if (dstSocket < 0) { 40 printf("%d\n", GetLastError()); 41 printf("ソケット生成エラー\n"); 42 } 43 44 /* 接続 */ 45 result = connect(dstSocket, (struct sockaddr *) &dstAddr, sizeof(dstAddr)); 46 if (result < 0) { 47 printf("%d\n", GetLastError()); 48 printf("バインドエラー\n"); 49 } 50 51 52 /* HTTP プロトコル生成 & サーバに送信 */ 53 sprintf(toSendText, "POST %s HTTP/1.1\r\n", httppath); 54 send(dstSocket, toSendText, strlen(toSendText), 0); 55 printf("%s", toSendText); 56 57 sprintf(toSendText, "Host: %s:%d\r\n", httphost, port); 58 send(dstSocket, toSendText, strlen(toSendText), 0); 59 printf("%s", toSendText); 60 61 sprintf(toSendText, "Content-Type: application/json\r\n", httphost, port); 62 send(dstSocket, toSendText, strlen(toSendText), 0); 63 printf("%s", toSendText); 64 65 sprintf(toSendText, "\r\n"); 66 send(dstSocket, toSendText, strlen(toSendText), 0); 67 printf("%s", toSendText); 68 69 // HTTP Body部の作成 70 // json作成 71 cJSON *auth = cJSON_CreateObject(); 72 73 cJSON_AddStringToObject(auth, "userName", "hoge"); 74 cJSON_AddStringToObject(auth, "password", "foo"); 75 sprintf(toSendText, "%s\r\n", cJSON_PrintUnformatted(auth), "str"); 76 send(dstSocket, toSendText, strlen(toSendText), 0); 77 printf("%s", toSendText); 78 79 //response 80 puts("result"); 81 while (1) { 82 memset(buf, 0, sizeof(buf)); 83 read_size = recv(dstSocket, buf, BUF_LEN, 0); 84 if (read_size > 0) { 85 printf("%s", buf); 86 } 87 else { 88 break; 89 } 90 } 91 92 closesocket(dstSocket); 93 WSACleanup(); 94 95 return 0; 96}

試したこと

1.APIの動作確認(問題なし)
プログラムが間違えているのか、APIサーバーに問題があるのか確かめるためにPOSTMANを使用してプログラムと同じアドレス、jsonでAPIを叩いたところ問題なくトークンが取得できました。

2.通信内容の比較(問題あり)
POSTMANを使用した際と、プログラムを使用した際に通信の内容がどのように異なっているのかをWiresharkを使用して確かめてみました。
POSTMANを使用した場合、WiresharkにJavaScript Object Notation: application/jsonという項目があり、展開すると送信したJSONデータが表示されます。

それに対して、作成したプログラムでは、JavaScript Object Notationの項目が表示されません。
というより、POSTMANで成功した場合には、ProtocolがHTTPのもので、Info部分にPOST /{path}/auth HTTP/1.1 (application/json)と記載されているパケット(?行の事)がありましたが、プログラムで作成したものに関しては全てTCPでした。
そもそも、リクエストが送信されていないのでしょうか?
個人的には、リクエストヘッダに"Content-Type: application/json"を入れて、bodyにjsonデータを入れればうまくいくといった認識でしたが、違うのでしょうか?

最後に

何か必要な情報等ありましたら、回答をお願いします。
質問を書きながらHTTPプロトコルの生成はしていますが、送信ができていないのでは?と思うところがありますが、具体的にどうすればよいかわからない状況です。

お力をお貸しください。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2019/04/19 08:48

POSTMANで送ったときのHTTPリクエストの内容と、完全に同じですか? "Content-Length:" フィールドが無いとか違いはありませんか? > そもそも、リクエストが送信されていないのでしょうか? sendの返り値を逐一、チェックしてみてください。また、Windowsの場合、connectやsend等のソケットAPIはGetLastError ではなく、WSAGetLastErrorを使います。 https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-send
asm

2019/04/19 10:14

> sendしている内容は以下の通りです。 > {"userName":"hoge,"password":"foo"} "hoge"の後ろのダブルクオーテーションが無いけどコピペミスでしょうか?
guest

回答1

0

ベストアンサー

こんにちは。

折角WireSharkでみているのでしたら、バイナリの部分を見比べたら相違がある筈です。その相違をなくせば通る筈ですよ。

httpのこのレベルのプロトコルには詳しくないのですが、リクエストをパケット分割する際には分割されていることがサーバ側で分からないと解析のしようがない筈です。ですが、それっぽいデータは付いていないように見えます。
このリクエストは1パケットで十分に送れそうですから、1回のsendで全て送ってみてはどうでしょう?

投稿2019/04/19 14:08

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問