C言語でのソケット通信の手順について説明します。
サーバー側
ソケット通信において、通信先からの接続を待つ側がサーバーとなります。
1.socket()にてソケットを生成する。
2.getservbyname()にてポート情報を得る。
これは/etc/servicesをサービス名で検索し、ポート番号を求めるための手順であり、ポート番号を決め打ちする場合は必要ない。
ポート番号を決め打ちする場合には、bind()の引数のsockaddr_in構造体に addr.sin_port = htons( 50000 ); の様に、ポート番号をネットワークバイトオーダーで設定する。
3.bind()にてソケットにポート番号及びIPアドレスを設定する
4.listen()にて接続を待つ
5.accept()にて接続を確立する。
6.以後、acceptにて取得したソケットにてソケットの送受信を行う。
先に生成した接続待ちの為のソケットと、acceptで取得した通信用のソケットの2つのソケットがあることに注意すること。
クライアント側
ソケット通信において、サーバーへ接続する側がクライアントとなります。
1.socket()にてソケットを生成する。
2.gethostbyname()にてホスト情報を得る。
これは/etc/hostsをホスト名で検索し、IPアドレスを求めるための手順であり、IPアドレスを決め打ちする場合は必要ない。
IPアドレスを決め打ちする場合には、connect()の引数のsockaddr_in構造体に sin.sin_addr.s_addr = inet_addr(“127.0.0.1”); の様にIPアドレスを設定する。
3.getservbyname()にてポート情報を得る。
4.connect()にてサーバー側に接続する
5.以後、connectしたソケットにてソケットの送受信を行う。
========== サーバー側 ============
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char** argv)
{
int fd;
int fd2;
struct servent *serv;
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
struct sockaddr_in from_addr;
char buf[2048];
// 受信バッファを初期化する
memset(buf, 0, sizeof(buf));
// ソケットを作成する
if (( fd = socket(AF_INET, SOCK_STREAM, 0 )) < 0 ) {
fprintf( stdout, "socket error : fd = %d\n", fd );
return -1;
}
serv = getservbyname( "vboxd", "tcp" );
if ( !serv ){
close( fd );
return -1;
}
// IPアドレス、ポート番号を設定
addr.sin_family = AF_INET;
addr.sin_port = serv->s_port;
addr.sin_addr.s_addr = INADDR_ANY;
// バインドする
if ( bind( fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
fprintf( stdout, "bind error\n" );
return -1;
}
// パケット受信待ち状態とする。待ちうけるコネクト要求は1
if ( listen( fd, 1 ) < 0 ) {
fprintf( stdout, "listen error\n" );
return -1;
}
// クライアントからの接続を確立する
if (( fd2 = accept(fd, (struct sockaddr *)&from_addr, &len )) < 0 ) {
fprintf( stdout, "accept error : fd2 = %d\n", fd2 );
return -1;
}
// パケット受信
if ( recv( fd2, buf, sizeof(buf), 0 ) < 0 ) {
fprintf( stdout, "recv");
return -1;
}
// パケット送受信用ソケットクローズ
close(fd2);
// 接続要求待ち受け用ソケットクローズ
close(fd);
// 受信データの出力
fprintf( stdout, "%s\n", buf );
return 0;
}
========== クライアント側 ==========
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char** argv)
{
int fd;
struct hostent *info;
struct servent *serv;
struct sockaddr_in addr;
char buff[2048];
// IPv4 TCP のソケットを作成する
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf( stdout, "socket error\n" );
return -1;
}
// hostsからホスト情報をを読み出す
info = gethostbyname("localhost");
if ( !info ){
close( fd );
fprintf( stdout, "gethostbyname error\n" );
return -1;
}
serv = getservbyname( "vboxd", "tcp" );
if ( !serv ){
close( fd );
fprintf( stdout, "getservbyname error\n" );
return -1;
}
// 送信先アドレスとポート番号を設定する
addr.sin_family = AF_INET;
addr.sin_port = serv->s_port;
addr.sin_addr = *(struct in_addr *)(info->h_addr_list[0]);
// サーバ接続
connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
sprintf( buff, "Thi is send Message" );
// パケットを送信
if ( send( fd, buff, strlen(buff), 0 ) < 0 ) {
close( fd );
fprintf( stdout, "send error\n" );
return -1;
}
close(fd);
return 0;
}
============ ここまで ============
上記サンプルプログラムを使用して発生した障害,問題などに関して,プログラムの作者および(株)アイズ・ソフトウェアは一切の責任を負いません。
使用はご自身の責任で行ってください。