C
C言語によるソケット通信のサンプルプログラムです。
ここでは、実験用に、1台のコンピュータでできるように、クライアントからループバックアドレス127.0.0.1に繋ぐようにしています。
あるウェブサイトを参考にしましたが、何処にあるか忘れましたので、言及出来ませんが、
初心者覚書です。
ソースコード
sserver
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
int sockfd;
int client_sockfd;
struct sockaddr_in addr;
socklen_t len = sizeof( struct sockaddr_in );
struct sockaddr_in from_addr;
char buf[1024];
// 受信バッファ初期化
memset( buf, 0, sizeof( buf ) );
// ソケット生成
if( ( sockfd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
perror( "socket" );
}
// 待ち受け用IP・ポート番号設定
addr.sin_family = AF_INET;
addr.sin_port = htons( 1234 );
addr.sin_addr.s_addr = INADDR_ANY;
// バインド
if( bind( sockfd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) {
perror( "bind" );
}
printf("waiting for client's connection..\n");
// 受信待ち
if( listen( sockfd, SOMAXCONN ) < 0 ) {
perror( "listen" );
}
// クライアントからのコネクト要求待ち
if( ( client_sockfd = accept( sockfd, (struct sockaddr *)&from_addr, &len ) ) < 0 ) {
perror( "accept" );
}
// 受信
int rsize;
while( 1 ) {
rsize = recv( client_sockfd, buf, sizeof( buf ), 0 );
if ( rsize == 0 ) {
break;
} else if ( rsize == -1 ) {
perror( "recv" );
} else {
printf( "receive:%s\n", buf );
sleep( 1 );
// 応答
printf( "send:%s\n", buf );
write( client_sockfd, buf, rsize );
}
}
// ソケットクローズ
close( client_sockfd );
close( sockfd );
return 0;
}
sclient
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
int sockfd;
struct sockaddr_in addr;
// ソケット生成
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0) ) < 0 ) {
perror( "socket" );
}
// 送信先アドレス・ポート番号設定
addr.sin_family = AF_INET;
addr.sin_port = htons( 1234 );
addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
// サーバ接続
connect( sockfd, (struct sockaddr *)&addr, sizeof( struct sockaddr_in ) );
// データ送信
char send_str[10];
char receive_str[10];
for ( int i = 0; i < 8; i++ ){
sprintf( send_str, "%d", i );
printf( "send:%d\n", i );
if( send( sockfd, send_str, 10, 0 ) < 0 ) {
perror( "send" );
} else {
recv( sockfd, receive_str, 10, 0 );
printf( "receive:%s\n", receive_str );
}
sleep( 1 );
}
// ソケットクローズ
close( sockfd );
return 0;
}
コンパイル
サーバは、cc sserver.c -o ss
、クライアントはcc sclient.c -o sc
でコンパイルしてください。
実験
まずsserverを立ち上げます。そして、もう一つの端末からsclientを立ち上げます。
そうすると、sclientから、8個のデータが送られてきてデータを表示し、終了です。
実験結果サーバ側
$ ./ss
waiting for client's connection..
receive:0
send:0
receive:1
send:1
receive:2
send:2
receive:3
send:3
receive:4
send:4
receive:5
send:5
receive:6
send:6
receive:7
send:7
実験結果クライアント側
$ ./sc
send:0
receive:0
send:1
receive:1
send:2
receive:2
send:3
receive:3
send:4
receive:4
send:5
receive:5
send:6
receive:6
send:7
receive:7
Python3
Pythonでも書いてみました。此れはCのバージョンと同じ動きをします。
Cに比べて、ずいぶんとスッキリと書くことが出来ます。
参考Qiita:【Pythonによる通信処理】
.encode()で、にバイナリにエンコードし、.decode()で、文字列にデコードします。utf-8をエンコードする時は、.encode('utf-8')でします。
ここでは、socket.gethostname()を使って、sserver.pyの自分のマシンのホストネームを得るようにしています。
sclient.pyでは、ループバックアドレス127.0.0.1に繋ぐようにしています。
#!/usr/bin/python3
import socket
port = 1234
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversock.bind((socket.gethostname(),port)) #IPとPORTを指定してバインドします
serversock.listen(10) #接続の待ち受けをします(キューの最大数を指定)
print('Waiting for connections...')
clientsock, client_address = serversock.accept() #接続されればデータを格納
for i in range ( 8 ):
rcvmsg = clientsock.recv(1024).decode()
print('Received : %s' % (rcvmsg))
s_msg = str(i)
print('Send : %s' % s_msg)
clientsock.sendall(s_msg.encode())
clientsock.close()
#!/usr/bin/python3
import socket
host = "127.0.0.1"
port = 1234
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #オブジェクトの作成を
します
client.connect((host, port)) #これでサーバーに接続します
for i in range(8):
message = str(i)
print('Send : %s' % message)
client.send(message.encode()) #データを送信します
response = client.recv(4096) #レシーブは適当な2の累乗にします(大きすぎるとダ>メ)
print('Received: %s' % response.decode())