--.--
--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

06.15
Fri
いちいちアドレスを設定したり構造体を定義するのはめんどいので、

TCP用にらくできるのを書いてみた。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>


#define True  1
#define False 0



/*
	
	以下の関数はTCPでネットワークプログラミングを行う上で基礎的な機能を提供します
	
	・tcpmake           新しいTCP用のソケットファイルディスクリプタを作る
	・tcphang           指定のホストに接続する
	・tcpwait           サーバになる
	・tcpaccept         クライアントを受け付ける                 *b
	・tcpGetDataExactly サイズ分正確に受信する                   *b
	・tcpGetHTTPHeader  \r\nで区切られるヘッダ部分のみ受信する 

    *bはブロッキングな関数
*/




/*
  -----------------------------------------------------------------------
  int tcpmake(void)
  

   tcp用のソケットを作成します
 
  return -1      異常終了
  return それ意外   ソケットファイルディスクリプタ
  -----------------------------------------------------------------------
 */

int tcpmake(void){
	
	int fd = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
	
	if (fd < 0)
	{
		return -1;
	}else{
		return fd;
	}
	
	
}




/*
	-----------------------------------------------------------------------
	int tcpwait
		(
			int ソケットファイルディスクリプタ , char *バインドするIPアドレス ,  
			int バインドするポート , int 接続キューの大きさ  
		)
		
	クライアントからの接続を待機できるように準備します
	
	return 0 正常終了
	return 1 異常終了
	-----------------------------------------------------------------------
*/


int tcpwait(int sockfd , char *ipaddress , int port , int backlog)
{
	struct sockaddr_in server;
	server.sin_port = htons(port);
	server.sin_family = AF_INET;
	inet_aton(ipaddress , &server.sin_addr);
	
	if (bind(sockfd , (struct sockaddr *)&server , sizeof(server)) == -1)
	{
		return 1;
	}
	
	if (listen(sockfd , backlog) == -1)
	{
		return 1;
	}
	
	return 0;
}

/*
	-----------------------------------------------------------------------------
	int tcpaccept
	(
		int ソケットファイルディスクリプタ
	)

	クライアントを一人acceptして新しいソケットファイルディスクリプタを返します
	構造体を返さないので、接続してきた人のIPとかはわかりません
	
	return -1    失敗
	return それ以外 成功
	-----------------------------------------------------------------------------
 */


int tcpaccept(int fd)
{
	
	struct sockaddr_in clientaddr;
	int len = sizeof(clientaddr);
	
	int newsock = accept(fd , (struct sockaddr *)&clientaddr , &len);
	
	return newsock;
	
}






/*	
	-----------------------------------------------------------------------
	int tcphang
		(
			int ソケットファイルディスクリプタ char *IPアドレス , int ポート番号
		)
	
	ipaddressのportに接続します。
	これはconnect関数で使うsockaddr_inを隠蔽します。
	
	return 0 正常に接続
	return 1 接続に失敗
	
	*補足*
	connect関数においての煩瑣な作業を軽減します
	-----------------------------------------------------------------------
*/

int tcphang(int sockfd , char *ipaddress , int port)
{
	
	struct sockaddr_in server;
	
	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	inet_aton(ipaddress , &server.sin_addr);
	int len = sizeof(server);
	
	int result = connect(sockfd , (struct sockaddr *)&server , len);
	
	return result * -1;
	
}




/*
	-----------------------------------------------------------------------
	int tcpGetDataExactly
		(
			int ソケットのファイルディスクリプタ , char *データを格納するための文字型配列 ,
			int 受信するサイズ
		)
		
	return 0  正常にsize分受信した
	return -1 途中で接続が切れた

	*補足*
	指定されたsize分正確に受信しptrに書き込むと思います
	接続が切れるか正確にsize分受信できるまでブロッキングします
	-----------------------------------------------------------------------
*/

int tcpGetDataExactly(int sockfd , char *ptr ,  int size)
{
	int allrecvedsize = 0;
	int justrecvedsize = 0;
	while (True){
		
		justrecvedsize = recv(sockfd , ptr + allrecvedsize , size - allrecvedsize , 0);
		allrecvedsize += justrecvedsize;
		
		if (allrecvedsize == size){
				return 0;
		}

		if (justrecvedsize == 0){
			
			if (allrecvedsize == size){
				return 0;
			}else{
				return -1;
			}
		}
	}
}




/*
	-----------------------------------------------------------------------
	int tcpGetHTTPHeader
		(
			int ソケットファイルディスクリプタ , char *データを格納する文字型配列 ,
			int 文字型配列の長さ , int 最大何行取得するか
		)
	
	return 0 http形式のヘッダーを正確に取得できた
	return 1 受信の途中で接続が切れた
	return 2 ヘッダの最大受信行数に達した
	return 3 初期化された文字配列の長さを超えそうになった

	*補足*
	HTTPヘッダ形式(\r\nで区切られた)のヘッダを受信しptrに書き込みます
	-----------------------------------------------------------------------
*/

int tcpGetHTTPHeader(int sockfd  , char *ptr , int ptrsize , int maxline){
	
	int flag = 0;
	int line = 0;
	int justrecvedsize = 0;
	int ptraxcel = 0;

	for(ptraxcel = 0;ptraxcel<ptrsize;ptraxcel++){
		
		justrecvedsize = recv(sockfd , ptr+ptraxcel , 1 , 0);
		
		if (justrecvedsize == 0)
				return 1;
		if ((*(ptr+ptraxcel) == '\r') || (*(ptr+ptraxcel) == '\n') ){
				flag += 1;
				if (flag == 4){ 
					return 0;
				}else if(flag == 2){
					line += 1;
				}
				if (line == maxline)
						return 2;
		}else{
			flag = 0;
		}
		
	}
	return 3;
}

スポンサーサイト

comment 0 trackback 0
トラックバックURL
http://telracsmoratori.blog.fc2.com/tb.php/118-ef053837
トラックバック
コメント
管理者にだけ表示を許可する
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。