[[Hirofumi Fujii Start Page]]

* TCP接続用 C library [#va1fa5f9]
通常 TCP接続を行う手順は、ほぼ決まっている。決まりきった使い方であるならば
一まとめにしておいた方が使いやすい。そのためのパッケージである。

面倒な(しかしよく使う)のがサーバに対し名前(hostname)で接続する場合
であろう。このパッケージは、ほとんどそのためにある。名前からアドレスを
取得して connect するまでを tcpopen() として用意した。

ここで示した tcpopen() は、
最初に取得したアドレスに対し connect() を行う(connect() の戻り値を返す)。
マルチホームなどの場合などでは別アドレスも試みるように変更するべきかも
知れない。

** ヘッダファイル tcplib.h [#m6cd4bcc]

 /* tcplib.h */
 
 #ifndef TCPLIB_H_INCLUDED
 #define TCPLIB_H_INCLUDED
 
 #ifdef WIN32
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #if (_WIN32_WINNT >= 0x0501)
 #define HAS_GETADDRINFO
 #endif	/* (_WIN32_WINNT > 0x0501) */
 #else
 #include <unistd.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 typedef int SOCKET;
 #define INVALID_SOCKET (-1)
 #define HAS_GETADDRINFO
 #endif	/* WIN32 */
 
 /* Function prototypes */
 #ifdef __cplusplus
 extern "C" {
 #endif	/* __cplusplus */
 
 int netlibstart(void);
 int netlibstop(void);
 
 SOCKET tcpsocket(void);
 int tcpopen(SOCKET sd, const char* host, int port);
 int tcplisten(SOCKET sd, int port, int backlog);
 int tcpclose(SOCKET sd);
 int tcpread(SOCKET sd, char* buf, int nbytes);
 int tcpwrite(SOCKET sd, const char* buf, int nbytes);
 
 #ifdef __cplusplus
 }
 #endif	/* __cplusplus */
 
 #endif	/* TCPLIB_H_INCLUDED */

tcplib.c
** 実装本体 tcplib.c [#ecb044be]

 /* tcplib.c
  *
 */
 
 #include "tcplib.h"
 #include <stdlib.h>
 #include <stdio.h>
 
 SOCKET
 tcpsocket(void)
 {
 	return socket(PF_INET, SOCK_STREAM, 0);
 }
 
 int
 tcpopen(SOCKET sd, const char* host, int port)
 {
 	struct sockaddr_in srvaddr;
 #ifdef HAS_GETADDRINFO
 	struct sockaddr_in* resaddr;
 	struct addrinfo hints;
 	struct addrinfo* res;
 	int err;
 #else
 	struct hostent *hp;
 	unsigned long inaddr;
 #endif	/* HAS_GETADDRINFO */
 
 	memset((char*)&srvaddr, 0, sizeof(srvaddr));
 	srvaddr.sin_family = AF_INET;
 	srvaddr.sin_port = htons((u_short)port);
 #ifdef HAS_GETADDRINFO
 	res = 0;
 	memset((char*)&hints, 0, sizeof(hints));
 	hints.ai_family = PF_INET;
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_protocol = 0;
 	if((err = getaddrinfo(host, 0, &hints, &res)) != 0)
 		return (-1);
 
 	resaddr = (struct sockaddr_in*)res->ai_addr;
 	srvaddr.sin_addr = resaddr->sin_addr;
 	freeaddrinfo(res);
 #else
 	if((inaddr = inet_addr(host)) != INADDR_NONE)
 		memcpy((char*)&srvaddr.sin_addr, (char*)&inaddr, sizeof(inaddr));
 	else
 	{
 		if((hp = gethostbyname(host)) == NULL)
 			return (-1);
 		if(hp->h_addrtype != AF_INET)
 			return (-1);
 		memcpy((char*)&srvaddr.sin_addr, (char*)hp->h_addr, hp->h_length);
 	}
 #endif	/* HAS_GETADDRINFO */
 	return connect(sd, (struct sockaddr*)&srvaddr, sizeof(srvaddr));
 }
 
 int
 tcplisten(SOCKET sd, int port, int backlog)
 {
 	struct sockaddr_in addr;
 
 	memset((char*)&addr, 0, sizeof(addr));
 	addr.sin_family = AF_INET;
 	addr.sin_addr.s_addr = htonl(INADDR_ANY);
 	addr.sin_port = htons((u_short)port);
 
 	if(bind(sd, (const struct sockaddr*)&addr, sizeof(addr)) == -1)
 		return (-1);
 
 	return listen(sd, backlog);
 }
 
 int
 tcpclose(SOCKET sd)
 {
 #ifdef WIN32
 	return closesocket(sd);
 #else
 	return close(sd);
 #endif	/* WIN32 */
 }
 
 int
 tcpread(SOCKET sd, char* buf, int nbytes)
 {
 	int nleft, nrecv;
 
 	nleft = nbytes;
 	while(nleft > 0)
 	{
 		nrecv = recv(sd, buf, nleft, 0);
 		if(nrecv < 0)
 			return nrecv;
 		else if(nrecv == 0)
 			break;
 		nleft -= nrecv;
 		buf += nrecv;
 	}
 	return (nbytes - nleft);
 }
 
 int
 tcpwrite(SOCKET sd, const char* buf, int nbytes)
 {
 	int nleft, nsent;
 
 	nleft = nbytes;
 	while(nleft > 0)
 	{
 		nsent = send(sd, buf, nleft, 0);
 		if(nsent <= 0)
 			return nsent;
 		nleft -= nsent;
 		buf += nsent;
 	}
 	return (nbytes - nleft);
 }
 
 int
 netlibstart(void)
 {
 #ifdef WIN32
 	WORD wVersion;
 	WSADATA wsaData;
 	wVersion = MAKEWORD(2,2);
 	if(WSAStartup( wVersion, &wsaData ))
 		return (-1);
 #endif	/* WIN32 */
 	return 0;
 }
 
 int
 netlibstop(void)
 {
 #ifdef WIN32
 	if(WSACleanup())
 		return (-1);
 #endif	/* WIN32 */
 	return 0;
 }


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS