linuxネットワーク通信-ソケット

7550 ワード

socketプログラミングはネットワークでよく使われるプログラミングであり,ネットワークにsocketキーワードを作成することでネットワーク間の通信を実現する.
1.TCP/IPプロトコルまずTCP/IPプロトコルを簡単に理解する:
iso 7階層アーキテクチャ
アプリケーション層
アプリケーション層は、アプリケーションプロセスに必要な情報交換とリモート操作を提供するだけでなく、アプリケーションプロセスのユーザーエージェントとして、意味的に意味のある情報交換を行うために必要な機能をいくつか完了する必要があります.
ひょうげんそう
2つの通信システム間の情報交換を処理するための表現であり、データフォーマット変換、データ暗号化と復号化、データ圧縮と復元などの機能を含む.
セッションレイヤ
同期した2つのセッション・ユーザー間のセッションを整理し、データの交換を管理します.
でんそう
信頼性の高いエンド・ツー・エンド・サービスをユーザーに提供し、メッセージを透過的に送信します.
ネットワーク層
ルーティングアルゴリズムを実行することによって、メッセージパケットに対して通信サブネットを介して最適な経路を選択する.
データチェーン層
物理層がビットストリーム伝送サービスを提供する上で、通信エンティティ間でデータリンク接続を確立し、フレーム単位のデータを伝送する
ぶつりそう
物理層の主な機能は、ビットストリームを透過的に伝送するために、物理伝送媒体を用いてデータリンク層に物理的接続を提供することである.
iso 7層アーキテクチャとは異なり、TCP/IPプロトコルは4層に分かれている
アプリケーション層
TFT P,HTTP,SNMP,FTP,SMTP,DNS,Telnetなど
でんそう
TCP,UDP
ネットワーク層
IP,ICMP,OSPF,EIGRP,IGMP
データチェーン層
SLIP,CSLIP,PPP,MTU
tcp/ipプロトコルでは、tcpは3回の握手を通じてtcpのリンクの最初の握手を確立した:クライアントはサーバに接続しようとし、サーバにsynパケットを送信し、syn=j、クライアントはSYN_に入るSENDステータスはサーバ確認待ちです.2回目の握手:サーバはクライアントsynパケットを受信して確認し(ack=j+1)、同時にクライアントにSYNパケット(syn=k)、すなわちSYN+ACKパケットを送信し、このときサーバはSYN_RECV状態3回目の握手:クライアントはサーバのSYN+ACKパケットを受け取り、サーバに確認パケットACK(ack=k+1)を送信し、このパケットの送信が完了し、クライアントとサーバはESTABLISHED状態に入り、3回の握手を完了する.
socketはアプリケーションの伝送層とアプリケーション層の間にsocket抽象層を設計し、伝送層の下層のサービスはsocket抽象層に提供され、socket抽象層はアプリケーション層に提供される.
2.socketプログラミング(1)ソケットの作成と破棄
ソケット関数を使用してソケットを作成する
#include
int socket(int domain,int type,int protocol)

パラメータdomain(ドメイン)通信の特性を決定する
ドメイン
説明
AF_INET
IPV 4インターネットドメイン
AF_INET6
IPV 6インターネットドメイン
AF_UNIX
UNIXドメイン
AF_UPSPEC
指定されていません
パラメータtypeはソケットのタイプを決定します
を選択します.
説明
SOCK_DGRAM
固定長さ、接続なし、信頼できないメッセージ伝達
SOCK_RAM
IPプロトコルのパケットインタフェース
SOCK_SEQPACKET
固定長、秩序、信頼性、接続向けのメッセージ伝達
SOCK_STREAM
秩序化された、信頼性の高い、双方向の、接続向けのバイトストリーム
パラメータprotocolは通常0であり、指定されたドメインとソケットタイプでデフォルトのプロトコルが選択されていることを示します.
呼び出しソケットはopen関数の呼び出しと似ており、I/O用のファイル記述子を得ることができます.ファイル文字が不要になった場合、close関数を呼び出してファイルやソケットへのアクセスを閉じます.
ソケットの通信は双方向であり,関数shutdownを用いてソケットのI/Oを禁止することができる.
#include
int   shutdown(int sockfd,int how);
                           :    0,    -1

パラメータhow:SHUT_RDリード端子を閉じ、SHUT_WRクローズライト端子
(2).バイト順大端バイト順:最大バイトアドレスに最低有効バイト小端バイト順が現れる:最小バイトアドレスは32ビット整数0 X 04030201に対して、最高有効バイトは04、最低は01である.大端を採用すると、最大バイトアドレスは01を含む.逆に、最小バイトアドレスは01を含む.
ネットワークプロトコルはバイト順を指定し、TCP/IPプロトコルスタックの場合は、大端バイト順を使用します.アプリケーションは、プロセッサのバイト順とネットワークのバイト順の間で変換する必要があります.TCP/IPアプリケーションの場合、変換に使用する関数は4つあります.
#include
uint32_t   htonl(uint32_t hostint32);     //host  to net           32      
uint16_t   htons(uint16_t hostint16);    //host  to net           16      
uint32_t   ntohl(uint32_t  netint32);     //net  to host           32      
uint16_t   ntohs(uint16_t netint16);    //net  to host           16      


(3)アドレスフォーマットlinuxでソケットアドレス用構造体sockaddr_in表示
struct sockaddr_in {
        short sin_family;                               //    ,ipv4 ipv6
        unsigned short sin_port;                   //  
        struct  in_addr sin_addr;                   //ip  
        unsigned char sin_zero[8];               //   ,    16   
};

(4)ソケットとアドレスをサーバに関連付ける前の周知のアドレス.関数bindを使用してアドレスとソケットを関連付けます
#include
int bind(int sockfd,const struct sockaddr *addr,socklen_t len)
   :    0,    -1

パラメータsockfd:socket()呼び出しによって返され、接続されていないソケット記述子(ソケット番号).パラメータaddr:ソケットsに割り当てられたローカルアドレス(名前)であり、その長さは可変であり、構造は通信ドメインによって異なる.パラメータlen:addrの長さを示します.
(5)ソケット接続関数connectの確立
#include
int connect(int sockfd,const struct sockaddr *addr,socklen_t len)
   :    0,    -1

パラメータsockfd:ローカルソケット記述子パラメータaddrはサーバアドレスパラメータlen:サーバアドレス長
関数listenサーバはlisten関数を呼び出して要求を受け入れることを宣言します
#include
int listen(int sockfd,int backlog)
   :    0,    -1

パラメータsockfd:ローカルで確立され、接続されていないソケット番号を識別し、サーバはリクエストを受信します.パラメータbacklog:プロセスがエンキューする未完了接続要求の数をプロンプトします.キューがいっぱいになると、サーバは余分な接続要求を拒否します.
関数acceptサーバがlietenを呼び出すと、使用するソケットは接続要求を受け入れることができます.acceptを使用して接続要求を取得し、接続を確立します.
#include
int accept(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict len)
   :       ,    -1

パラメータsockfd:ローカルソケット記述子パラメータaddr:クライアントソケットアドレス
(6)データ伝送には6つの関数があり,データ伝送に用いられ,3つの送信,3つの受信がある.ここでは2つの関数sendだけを書きます
#include
ssize_t send(int sockfd,const void *buf,size_t nbytes,int flags);
   :       ,    -1

send関数はwrite関数と似ており,flagsパラメータを1つ増やしてこれらのflagをまとめた.
MSG_CONFIRM
アドレスマッピングを有効に保つためにリンク層フィードバックを提供する
MSG_DONTROUTE
パケットをローカルネットワークからルーティングしない
MSG_DONTWAIT
非ブロック操作の許可
MSG_EOR
プロトコルがサポートされている場合は、タグレコードが終了します.
MSG_MORE
パケットの送信を遅延し、より多くのデータを書き込むことができます.
MSG_NOSIGNAL
接続されていないソケットを書くときにSIGPIPE信号は発生しません
MSG_OOB
プロトコルがサポートされている場合は、帯域外データを送信します.
関数recv
#include
ssize_t recv(int sockfd,void *buf,size_t nbytes,int flags)


read関数と同様にflags制御フラグが1つ増えました
MSG_GMSG_CLOEXEC
ビットunixドメインソケットで受信したファイル記述子設定実行時クローズフラグ
MSG_DONTWAIT
非ブロック操作の有効化
MSG_ERR
エラーメッセージをセカンダリデータとして受信
MSG_OOB
プロトコルがサポートされている場合は、帯域外データを取得します.
MSG_PEEK
パケットの内容を返し、実際にパケットを取り出さない
MSG_TRUNC
パケットが切断されても、パケットの長さが返されます.
MSG_WAIT
すべてのデータが使用可能になるまで待機
サーバー・インスタンス
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	int sockfd;
	int clitfd
	struct sockaddr_in serv_addr;
	struct sockaddr_in clint_addr;
	memset(&serv_addr, 0, sizeof(serv_addr));
	char buffer[]="hello I'm a server"
	
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)       //        
	{
		fprintf(stderr,"socket failed
"); exit(1); } serv_addr.sin_family=AF_INET; // IP, serv_addr.sin_addr.s_addr=htonl(127.0.0.1); serv_addr.sin_port=htons(8080); bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)); // listen(sockfd,10); // clitfd=accept(sockfd,(struct sockaddr*)&clint_addr,(socklen_t)(sizeof(clint_addr))); // , send(clitfd,buffer,sizeof(buffer),0); // close(sockfd); // close(clitfd); return 0; }

クライアントルーチン
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	struct sockaddr_in clint_addr;
	struct sockaddr_in serv_addr;
	int  clintfd;
	char buffer[100];
	memset(&clint_addr, 0, sizeof(clint_addr));
	
	if((clintfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	{
		fprintf(stderr,"socket failed
"); exit(1); } clint_addr.sin_family=AF_INET; clint_addr.sin_addr.s_addr = htonl(127.0.0.1); clint_addr.sin_port = htons(1234); if((connect(clintfd,(struct sockaddr_in*)&serv_addr,sizeof(serv_addr)))==-1) { fprintf(stderr,"connect failed
"); exit(1); } recv(clintfd,buffer,sizeof(buffer),0) close(clintfd); return 0; }