ネットワークプログラミングfhdの基礎学習
8737 ワード
プログラミングは長い間やりましたが、あまり深くない感じがします.何でも少しできます.仕事も解決できます.
ネットワークプログラミングは前に接触したことがありますが、今回はシステムの勉強を通して、今後も引き続き整理学習を行います.
先ほど記事を読みました.http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html吸収のまとめ:
(一) Linuxネットワークプログラミング
1)TCP/UDP紹介
TCP(Transfer Control Protocol)転送制御プロトコルは、接続に向けたプロトコルであり、私たちのネットワークプログラムがこのプロトコルを使用する場合、 ネットワークは私達のクライアントとサービスの接続が信頼できて、安全です. このような契約は私達のネットワークプログラムの接続が信頼できるとは保証できません.だから、私達が作成しているプログラムは一般的にTCPプロトコルを採用しています. コマンドnetstatは、ネットワークの接続を表示するためのもので、ルーティングテーブルやインターフェース統計などのネットワークの情報.netstatには多くのオプションがあります. 私たちがよく使うオプションは-naです.詳細なネットワーク状態を表示します.他のオプションはヘルプマニュアルを使って詳細な情報を得ることができます.
2)ホテルネット telnetはリモートに登録するためのプログラムですが、このプログラムを使ってサービスの調整ができます. 例えば、私達のサーバープログラムは8888ポートを傍受しています. テルnet local Host 8888 サービスの状況を調べに来ました.
3)pingpingプログラムは、ネットワークの状態が正常かどうかを判断するために使用されます. ping 192.168.0.1 192.168.0.1のハードウェア接続が正常かどうかを確認したいという意味です.
(二) Linuxネットワークプログラミング--ファーストクラスのネットワーク関数紹介(TCP)
通信のファイル・ディスクリプタを返します.このディスクリプタは普通のファイルのディスクリプタとして動作します.これはLinuxのデバイスの非依存性の利点です. ディスクリプタへの読み書き操作によって、ネットワーク間のデータ交流ができます.
1)socket int socket(int domain,int type,int protocol)
domain:私たちのネットワークプログラムがあるホストが使っている通信協商族(AFuUNIXやAFuINETなど)を説明します. AF_UNIXは単一のUnixシステムのプロセス間通信のみに使用できます. AF_INETはインターネットを対象としていますので、リモートでの操作が可能です. ホスト間通信(私たちman socketの場合、domainはAF_u*ではなくPF__*であり、glibcはposixの実現であるため、AFの代わりにPFで代替できます. でも私達は全部使えます.
type:私たちのネットワークプログラムで採用している通信プロトコル(SOCK__STREAM、SOCK_uDGRAMなど) SOCK_STREAMは私達が使うのがTCPプロトコルであることを示しています.このように順序的に、信頼できる、双方向、接続に向けたビットストリームを提供します. SOCK_DGRAMは私達が使っているのがUDPプロトコルであることを示しています.
protocol:typeを指定しましたので、この場所は普通0で代えればいいです.socketはネット通信のために基本的な準備をします. 成功した時はファイルの記述子を返します.失敗した時は-1を返します.エラーノを見てエラーの詳細が分かります.
2)ビン int bit(int sockfd、struct sockaddr*myuader、int addrlen)
sockfd:socketで呼び出されて戻ってきたファイル記述子です.
addrlen:sockaddr構造の長さです.
my_addr:sockaddrを指すポインタです.中にsockaddrの定義があります.
struct sockaddr{ unisgned shart asufamily; char saudta[14]; };
しかし、システムの互換性のために、私たちはこのヘッダファイルを使わずに、他の構造を使っています. struct sockaddruin{ unsigned shart sinufamily unsigned shott int sinuport struct inudr sinudr; unsigned char sinzero[8]; } 私たちは主にインターネットを使います. sinufamilyは一般にAFuINETであり、 sinuuadrはINADDRAYに設定されており、どのホストと通信できるかを示しています. sinuplortは私たちが監聴するポート番号です.sinuzo[8]は充填用です. bindはローカルのポートとsocketから返されたファイル記述子を結びつけます.成功は0に戻ります.失敗はsocketと同じです.
3)listen int listen(int sockfd,int backlogn)
sockfd:bind後のファイル記述子です.
backlogs:設定要求の列の最大長さ.複数のクライアントプログラムとサービス端末が接続されている場合、これを使って紹介できる列の長さを表します. listen関数は、bindのファイル記述子を傍受ソケットに変更します.
4)accept int accept(int sockfd,struct sockaddr*addr,int*addrlen)
sockfd:listen後のファイル記述子です.
addr,addrlenはクライアントのプログラムに記入するためのもので,サーバー側は転送ポインタだけでいいです.bind,listen,acceptはサーバー側で使う関数です. acceptを呼び出した時、サーバー側のプログラムはずっとブロックされます.接続ができたクライアントがあります.acceptが成功した時に最後のサーバー側のファイル記述子に戻ります. この時、サーバー側はこのディスクリプタにメッセージを書くことができます.失敗した時は-1に戻ります.
5)connect int connect(int sockfd,struct sockaddr*servuudr,int addrlen)
sockfd:socketが返したファイル記述子.
servuudr:サーバー側の接続情報を格納しています.その中でもsinuddはサーバー側のアドレスです.
addrlen:servuaderの長さ
connect関数はクライアントがサービスと接続するために使用します.成功したら0に戻ります.sockfdはサービスと通信するファイル記述子が失敗したら-1に戻ります.
(三)例
1)サービス端末の手順
全体的には、ネットワークプログラムは、クライアントとサーバ端の2つの部分から構成されています.
サーバー側socket-->bind->listen-->accept
クライアントsocket-->connect
ネットワークプログラミングは前に接触したことがありますが、今回はシステムの勉強を通して、今後も引き続き整理学習を行います.
先ほど記事を読みました.http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html吸収のまとめ:
(一) Linuxネットワークプログラミング
1)TCP/UDP紹介
TCP(Transfer Control Protocol)転送制御プロトコルは、接続に向けたプロトコルであり、私たちのネットワークプログラムがこのプロトコルを使用する場合、 ネットワークは私達のクライアントとサービスの接続が信頼できて、安全です. このような契約は私達のネットワークプログラムの接続が信頼できるとは保証できません.だから、私達が作成しているプログラムは一般的にTCPプロトコルを採用しています. コマンドnetstatは、ネットワークの接続を表示するためのもので、ルーティングテーブルやインターフェース統計などのネットワークの情報.netstatには多くのオプションがあります. 私たちがよく使うオプションは-naです.詳細なネットワーク状態を表示します.他のオプションはヘルプマニュアルを使って詳細な情報を得ることができます.
2)ホテルネット telnetはリモートに登録するためのプログラムですが、このプログラムを使ってサービスの調整ができます. 例えば、私達のサーバープログラムは8888ポートを傍受しています. テルnet local Host 8888 サービスの状況を調べに来ました.
3)pingpingプログラムは、ネットワークの状態が正常かどうかを判断するために使用されます. ping 192.168.0.1 192.168.0.1のハードウェア接続が正常かどうかを確認したいという意味です.
(二) Linuxネットワークプログラミング--ファーストクラスのネットワーク関数紹介(TCP)
通信のファイル・ディスクリプタを返します.このディスクリプタは普通のファイルのディスクリプタとして動作します.これはLinuxのデバイスの非依存性の利点です. ディスクリプタへの読み書き操作によって、ネットワーク間のデータ交流ができます.
1)socket int socket(int domain,int type,int protocol)
domain:私たちのネットワークプログラムがあるホストが使っている通信協商族(AFuUNIXやAFuINETなど)を説明します. AF_UNIXは単一のUnixシステムのプロセス間通信のみに使用できます. AF_INETはインターネットを対象としていますので、リモートでの操作が可能です. ホスト間通信(私たちman socketの場合、domainはAF_u*ではなくPF__*であり、glibcはposixの実現であるため、AFの代わりにPFで代替できます. でも私達は全部使えます.
type:私たちのネットワークプログラムで採用している通信プロトコル(SOCK__STREAM、SOCK_uDGRAMなど) SOCK_STREAMは私達が使うのがTCPプロトコルであることを示しています.このように順序的に、信頼できる、双方向、接続に向けたビットストリームを提供します. SOCK_DGRAMは私達が使っているのがUDPプロトコルであることを示しています.
protocol:typeを指定しましたので、この場所は普通0で代えればいいです.socketはネット通信のために基本的な準備をします. 成功した時はファイルの記述子を返します.失敗した時は-1を返します.エラーノを見てエラーの詳細が分かります.
2)ビン int bit(int sockfd、struct sockaddr*myuader、int addrlen)
sockfd:socketで呼び出されて戻ってきたファイル記述子です.
addrlen:sockaddr構造の長さです.
my_addr:sockaddrを指すポインタです.中にsockaddrの定義があります.
struct sockaddr{ unisgned shart asufamily; char saudta[14]; };
しかし、システムの互換性のために、私たちはこのヘッダファイルを使わずに、他の構造を使っています. struct sockaddruin{ unsigned shart sinufamily unsigned shott int sinuport struct inudr sinudr; unsigned char sinzero[8]; } 私たちは主にインターネットを使います. sinufamilyは一般にAFuINETであり、 sinuuadrはINADDRAYに設定されており、どのホストと通信できるかを示しています. sinuplortは私たちが監聴するポート番号です.sinuzo[8]は充填用です. bindはローカルのポートとsocketから返されたファイル記述子を結びつけます.成功は0に戻ります.失敗はsocketと同じです.
3)listen int listen(int sockfd,int backlogn)
sockfd:bind後のファイル記述子です.
backlogs:設定要求の列の最大長さ.複数のクライアントプログラムとサービス端末が接続されている場合、これを使って紹介できる列の長さを表します. listen関数は、bindのファイル記述子を傍受ソケットに変更します.
4)accept int accept(int sockfd,struct sockaddr*addr,int*addrlen)
sockfd:listen後のファイル記述子です.
addr,addrlenはクライアントのプログラムに記入するためのもので,サーバー側は転送ポインタだけでいいです.bind,listen,acceptはサーバー側で使う関数です. acceptを呼び出した時、サーバー側のプログラムはずっとブロックされます.接続ができたクライアントがあります.acceptが成功した時に最後のサーバー側のファイル記述子に戻ります. この時、サーバー側はこのディスクリプタにメッセージを書くことができます.失敗した時は-1に戻ります.
5)connect int connect(int sockfd,struct sockaddr*servuudr,int addrlen)
sockfd:socketが返したファイル記述子.
servuudr:サーバー側の接続情報を格納しています.その中でもsinuddはサーバー側のアドレスです.
addrlen:servuaderの長さ
connect関数はクライアントがサービスと接続するために使用します.成功したら0に戻ります.sockfdはサービスと通信するファイル記述子が失敗したら-1に戻ります.
(三)例
1)サービス端末の手順
/******* (server.c) ************/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd,new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size,portnumber;
char hello[]="Hello! Are You Fine?
";
if(argc!=2)
{
fprintf(stderr,"Usage:%s portnumber\a
",argv[0]);
exit(1);
}
if((portnumber=atoi(argv[1]))<0)
{
fprintf(stderr,"Usage:%s portnumber\a
",argv[0]);
exit(1);
}
/* socket */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket error:%s
\a",strerror(errno));
exit(1);
}
/* sockaddr */
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(portnumber);
/* sockfd */
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Bind error:%s
\a",strerror(errno));
exit(1);
}
/* sockfd */
if(listen(sockfd,5)==-1)
{
fprintf(stderr,"Listen error:%s
\a",strerror(errno));
exit(1);
}
while(1)
{
/* , */
sin_size=sizeof(struct sockaddr_in);
if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"Accept error:%s
\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %s
",
inet_ntoa(client_addr.sin_addr));
if(write(new_fd,hello,strlen(hello))==-1)
{
fprintf(stderr,"Write Error:%s
",strerror(errno));
exit(1);
}
/* */
close(new_fd);
/* */
}
close(sockfd);
exit(0);
}
2)クライアントプログラム/******* client.c ************/
/******* client.c ************/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd;
char buffer[1024];
struct sockaddr_in server_addr;
struct hostent *host;
int portnumber,nbytes;
if(argc!=3)
{
fprintf(stderr,"Usage:%s hostname portnumber\a
",argv[0]);
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"Gethostname error
");
exit(1);
}
if((portnumber=atoi(argv[2]))<0)
{
fprintf(stderr,"Usage:%s hostname portnumber\a
",argv[0]);
exit(1);
}
/* sockfd */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket Error:%s\a
",strerror(errno));
exit(1);
}
/* */
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnumber);
server_addr.sin_addr=*((struct in_addr *)host->h_addr);
/* */
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Connect Error:%s\a
",strerror(errno));
exit(1);
}
/* */
if((nbytes=read(sockfd,buffer,1024))==-1)
{
fprintf(stderr,"Read Error:%s
",strerror(errno));
exit(1);
}
buffer[nbytes]='\0';
printf("I have received:%s
",buffer);
/* */
close(sockfd);
exit(0);
}
3)MakeFileここでGNUのmakeユーティリティを使ってコンパイルします.makeについての詳細はMakeの使用説明を見てください.######### Makefile ###########
all:server client
server:server.c
gcc $^ -o $@
client:client.c
gcc $^ -o $@
(四)まとめ全体的には、ネットワークプログラムは、クライアントとサーバ端の2つの部分から構成されています.
サーバー側socket-->bind->listen-->accept
クライアントsocket-->connect