応用プログラミング I 6/29
1
任意の IP アドレス対応とバッファ処理
元(HTTP クライアントサンプル) 変更部分 課題 16 char targetad[16]="157.105.104.235"; //学芸大
int port=80;
char targetad[16];
int port=80;
target.sin_addr.s_addr=inet_addr(targetad); scanf("%s", targetad);
target.sin_addr.s_addr=inet_addr(targetad);
if(target.sin_addr.s_addr==INADDR_NONE){
fprintf(strerr, "Wrong IP addr.¥n"); exit(1);
}
// エラー処理:変換に失敗すると
// inet_addr() はINADDR_NONEを返す
bytes=recv(sock, buf, sizeof(buf) - 1, 0);
buf[bytes]='¥0'; //文字列終端¥0 をセット fputs(buf, stdout); //末尾に改行¥nを出力しない
for(;;) {
bytes=recv(sock, buf, sizeof(buf)-1, 0);
if(bytes==0) break;
buf[bytes]='¥0'; //文字列終端¥0
fputs(buf, stdout); //改行¥nを出力しない }
PROXY アクセス
元(HTTP クライアントサンプル) 変更部分 課題 17 char targetad[16]="157.105.104.235"; //学芸大
int port=80;
char targetad[16]="157.105.104.233"; //proxy int port=10081;
char host[256];
scanf("%s", host);
bytes=sprintf(buf, "GET / HTTP/1.0¥n¥n");
send(sock, buf, bytes, 0);
bytes=recv(sock, buf, sizeof(buf) - 1, 0);
buf[bytes]='¥0'; //文字列終端¥0 をセット fputs(buf, stdout); //末尾に改行¥nを出力しない
bytes=sprintf(buf, "GET / HTTP/1.1¥r¥n"
”Host: %s¥r¥n¥r¥n", host);
send(sock, buf, bytes, 0);
for(;;) {
bytes=recv(sock, buf, sizeof(buf)-1, 0);
if(bytes==0) break;
buf[bytes]='¥0'; //文字列終端¥0
fputs(buf, stdout); //改行¥nを出力しない }
応用プログラミング I 6/29
2
ネットワーク関連関数一覧
send / recv
はコネクション通信の送受信関数で,connectしてから使う。sendto / recvfrom
は使うたびに通信相手を指定することができ,コネクションレス通信(UDP)に使 うことができる。機能 ソケット
sockfd
により,指定されたアドレスto
にデータbuff
からnbytes
バイト分を 送信する。形式
int sendto(int sockfd, char *buff, int nbytes, int flags, struct sockaddr
*to, int addrlen);
flags
はオプション。addrlenはto
構造体変数の大きさ。戻り値 送信したデータのバイト数。
機能 ソケット
sockfd
からデータを受信し,データbuff
に最大nbytes
バイトで書きだす。データが到着するまでプログラムはブロックする。データの送信元は
from
で知ることがで きる。形式
int recvfrom(int sockfd, char *buff, int nbytes, int flags, struct sockaddr *from, int *addrlen);
flags
はオプション。addrlenはfrom
構造体変数の大きさを返す変数のポインタ。戻り値 受信したデータのバイト数。
IP アドレス変換関数 (sys/socket.h, netinet/in.h)
機能 文字列
str
で表されるIP
アドレスを32
ビット表現に変換する 形式in_addr_t inet_addr(const char *str);
戻り値
32
ビット表現のIP
アドレス。文字列str
の形式にエラーがある場合はINADDR_NONE
が 変える。255.255.255.255のアドレスとINADDR_NONE
は区別できない。機能
32
ビット表現のIP
アドレスinaddr
を文字列に変換する 形式char *inet_ntoa(const in_addr_t inaddr);
戻り値
32
ビット表現のIP
アドレスを,ドット区切りの10
進数文字列表記(10.11.12.13など)に変換する。
応用プログラミング I 6/29
3 UDP
トランシーバサンプル(プロトタイプ)#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
int main() {
ネットワークプログラミング 共通
char targetad[16]="127.0.0.1";
int port=9000; 接続先アドレスを設定
接続先と打ち合わせたポート char buf[4096];
int bytes;
SOCKET sock;
SOCKADDR_IN local={AF_INET, htons(port), {INADDR_ANY}};
SOCKADDR_IN target={AF_INET, htons(port), {inet_addr(targetad)}};
SOCKADDR_IN guest;
int lenGuest=sizeof(guest);
アドレス構造体
(sockaddr_in)の初期化
sock=socket(AF_INET, SOCK_DGRAM, 0); //UDP bind(sock, (SOCKADDR*)&local, sizeof(local));
ソケット作成 9000番で受け付ける bytes=sprintf(buf, "#Connected. Please start to talk.¥n");
sendto(sock, buf, bytes+1, 0, (SOCKADDR*)&target, sizeof(target));
for(;;) { //recv
recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR*)&guest, &lenGuest);
fputs(buf, stdout);
if(buf[0]=='.') break;
//send printf("> ");
fgets(buf, sizeof(buf), stdin);
sendto(sock, buf, strlen(buf)+1, 0, (SOCKADDR*)&target, sizeof(target));
if(buf[0]=='.') break;
}
先発のメッセージは捨てられ る。後発のメッセージでシェ イクハンドが成立
受信部
データの発信元の情報は guest構造体変数に入る データ先頭の‘.’で終了 送信部
先頭‘.’で終了
close(sock); ソケット終了
return 0;
}
課題
18
現在のプログラムは,誰かと通信中に別の接続先からの受信があると,それを受け付けてしまい,元の 接続先との通信が破たんする。受信データの送信元を確認して,接続先でなければ無視するようにしな さい(もしくは断りのメッセージを返す)。また,受信したメッセージの前に,送信元の