戻る

LINUX間通信の準備                  2012.9.7

サーバとのI/FとしてUDPにて通信を行えるようにしておきます。
これは、現在XPORTとPICマイコンでサーバ(ALIX。3D3)と通信しているもの等を
Raspberry PiとPICマイコンに置き換える準備です。

(TCPでなくUDPの理由は、マイコン制御とI/Fにおいて使い勝手が良い為)


サーバ側送受信の基本形

コンパイルと実行テスト

サーバ側

root@ALIX:/home/xyz/gcc:/# gcc -o us001 us001.c
root@ALIX:/home/xyz/gcc:/#
./us001

クライアント側

root@pi-170:/home/xyz/gcc:/# gcc -o uc001 uc001.c
root@pi-170:/home/xyz/gcc:/#
./uc001

ソースファイル:us001.c

//
// linux UDPによるLAN接続(サーバ側:基本型)
//
// recv timeout 10sec
//
// v001. 2012.9.7
//

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h> // memset対応

#define PORT1 12345
#define PORT2 12346
#define C1 "192.168.0.170"
#define C2 "192.168.0.171"

int sock1,sock2;
struct sockaddr_in s1_addr , s2_adds;
struct sockaddr_in cc_addr;
char r1_buf[2048];
char r2_buf[2048];
char s_buf[2048];

char senderstr[16];
struct sockaddr_in senderinfo;
socklen_t addrlen;
// ------------------------------------------------------------
// ------------------------------------------------------------
int udp_recv(){
fd_set fds, readfds;
struct timeval tv;
int maxfd;
int n,ret;
while(1){
// ------------------------------------------------------------
// 受信ソケット1
// 受信ソケット2
// -----------------------------
sock1 = socket(AF_INET, SOCK_DGRAM, 0);
// sock2 = socket(AF_INET, SOCK_DGRAM, 0);
if(sock1 < 0){
printf("socker Error\n");
return(-1);
}
// if(sock2 < 0){
// printf("socker Error\n");
// return(-1);
// }
s1_addr.sin_family = AF_INET;
// s2_addr.sin_family = AF_INET;
s1_addr.sin_port = htons(PORT1);
// s2_addr.sin_port = htons(PORT2);
s1_addr.sin_addr.s_addr = INADDR_ANY;
// s2_addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock1, (struct sockaddr *)&s1_addr, sizeof(s1_addr));
// ret = bind(sock2, (struct sockaddr *)&s2_addr, sizeof(s2_addr));
// -----------------------------
FD_ZERO(&readfds); //fd_setの初期化
FD_SET(sock1, &readfds); // selectで待つ読込みソケットとしてsock1を登録
tv.tv_sec = 10; //10秒でタイムアウトするように
tv.tv_usec = 0;

// if(sock1 > sock2){maxfd = sock1;}
// else{maxfd = sock2;}
maxfd = sock1; // ファイルディスクリプタの最大値

/* 読み込み用fd_setを毎回初期化する */
memcpy(&fds, &readfds, sizeof(fd_set));

/* 設定されたソケットが読込み可能になるまで待つ */
// -----------------------------
n = select(maxfd+1, &fds, NULL, NULL, &tv);
// --------------------------------------------------------------------------------------
// maxfd+1 : ファイルディスクリプタの最大値に 1 を足したもの
// &fds : recvやrecvfromによる受信を監視するファイルディスクリプタのfd_set型をポインタ指定
// --------------------------------------------------------------------------------------
if (n == 0){ // タイムアウトの場合にselectは0を返す
printf("[udp_recv]timeout\n");
break;
}
// -----------------------------
if (FD_ISSET(sock1, &fds)) { // sock1に読み込み可能データがある場合
memset(r1_buf, 0, sizeof(r1_buf));

/* recvfrom()にてUDPソケットからデータを受信する */
addrlen = sizeof(senderinfo);
n = recvfrom(sock1, r1_buf, sizeof(r1_buf) - 1, 0,
(struct sockaddr *)&senderinfo, &addrlen);
/* 送信元に関する情報を表示 */
inet_ntop(AF_INET, &senderinfo.sin_addr, senderstr, sizeof(senderstr));
printf("[udp_recv]ip=[%s]port=[%d]\n", senderstr, ntohs(senderinfo.sin_port));
/* 受信データの表示 */
printf("[udp_recv1]%s\n", r1_buf);
}
// -----------------------------
// if (FD_ISSET(sock2, &fds)) { // sock2に読み込み可能データがある場合
// memset(r2_buf, 0, sizeof(r2_buf));

/* recvfrom()にてUDPソケットからデータを受信する */
// addrlen = sizeof(senderinfo);
// n = recvfrom(sock2, r2_buf, sizeof(r2_buf) - 1, 0,
// (struct sockaddr *)&senderinfo, &addrlen);

/* 送信元に関する情報を表示 */
// inet_ntop(AF_INET, &senderinfo.sin_addr, senderstr, sizeof(senderstr));
// printf("[udp_recv2]ip=[%s]port=[%d]\n", senderstr, ntohs(senderinfo.sin_port));

/* 受信データの表示 */
// printf("[udp_recv]%s\n", r2_buf);
// -----------------------------
// }
}
// -----------------------------
close(sock1);
// close(sock2);
printf("[udp_recv] fin\n");
return(0);
}
// ------------------------------------------------------------
// ------------------------------------------------------------
int udp_send(int port_no , char ip_adds[]){
sock1 = socket(AF_INET, SOCK_DGRAM, 0);
if(sock1 < 0){
printf("socker Error\n");
return(-1);
}
cc_addr.sin_family = AF_INET;
cc_addr.sin_port = htons(port_no);
cc_addr.sin_addr.s_addr = inet_addr(ip_adds);
sendto(sock1, s_buf, strlen(s_buf), 0, (struct sockaddr *)&cc_addr, sizeof(cc_addr));
close(sock1);
return(0);
}
// ------------------------------------------------------------
// ------------------------------------------------------------
int main(){
int ret;
int port_no;
char ip_adds[20];
ret = udp_recv(); // data-recv
if(ret < 0){return -1;}
strcpy(s_buf,r1_buf);
port_no = PORT1;
strcpy( ip_adds , C1);
ret = udp_send(port_no , ip_adds); // data-send
if(ret < 0){return -1;}
return 0;
}


トップに戻る

ソースファイル:uc001.c

//
// linux UDPによるLAN接続(クライアント側:基本型)
// (Rasspberry Pi)
// recv timeout 10sec
//
// v001. 2012.9.7
//
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h> // memset対応

#define PORT 12345
// #define Send_IPadds "127.0.0.1"
#define Send_IPadds "192.168.0.100"
#define My_IPadds "192.168.0.170"

int sock1 ;
struct sockaddr_in ss_addr;
struct sockaddr_in cc_addr;
char s_buf[2048];
char r1_buf[2048];

char senderstr[16];
struct sockaddr_in senderinfo;
socklen_t addrlen;

// ---------------------------------------------------------
// ---------------------------------------------------------
int udp_send(){

printf("send-data = "); // コンソールデータ入力
scanf("%s",s_buf); // コンソールデータ入力
sock1 = socket(AF_INET, SOCK_DGRAM, 0);
if(sock1 < 0){
printf("socker Error\n");
return(-1);
}
ss_addr.sin_family = AF_INET;
ss_addr.sin_port = htons(PORT);
ss_addr.sin_addr.s_addr = inet_addr(Send_IPadds);
// sendto(sock1 , "HELLO", 5, 0, (struct sockaddr *)&ss_addr, sizeof(ss_addr));
// sendto(sock1 , My_IPadds, sizeof(My_IPadds), 0, (struct sockaddr *)&ss_addr, sizeof(ss_addr));
sendto(sock1 , s_buf, sizeof(s_buf), 0, (struct sockaddr *)&ss_addr, sizeof(ss_addr));
close(sock1 );

printf("send end !\n");

}
// ---------------------------------------------------------
// ---------------------------------------------------------
int udp_recv(){
fd_set fds, readfds;
int maxfd;
int n,ret;
struct timeval tv;

while(1){
sock1 = socket(AF_INET, SOCK_DGRAM, 0);
if(sock1 < 0){
printf("socker Error\n");
return(-1);
}
cc_addr.sin_family = AF_INET;
cc_addr.sin_port = htons(PORT);
cc_addr.sin_addr.s_addr = inet_addr(My_IPadds);
ret = bind(sock1, (struct sockaddr *)&cc_addr, sizeof(cc_addr));
FD_ZERO(&readfds); //fd_setの初期化
FD_SET(sock1, &readfds); // selectで待つ読込みソケットとしてsock1を登録
tv.tv_sec = 10; //10秒でタイムアウトするように
tv.tv_usec = 0;

/* 読み込み用fd_setの初期化 */
/* selectが毎回内容を上書きしてしまうので、毎回初期化する */

memcpy(&fds, &readfds, sizeof(fd_set));

/* fdsに設定されたソケットが読込み可能になるまで待つ */

n = select(sock1+1, &fds, NULL, NULL, &tv);
if (n == 0){ // タイムアウトの場合にselectは0を返す
printf("[udp_recv]timeout\n");
break;
}

/* sock1に読み込み可能データがある場合 */

if (FD_ISSET(sock1, &fds)){ // sock1に読み込み可能データがある場合
memset(r1_buf, 0, sizeof(r1_buf));

/* recvfrom()を利用してUDPソケットからデータを受信 */
addrlen = sizeof(senderinfo);
n = recvfrom(sock1, r1_buf, sizeof(r1_buf) - 1, 0,
(struct sockaddr *)&senderinfo, &addrlen);
/* 送信元に関する情報を表示 */
inet_ntop(AF_INET, &senderinfo.sin_addr, senderstr, sizeof(senderstr));
printf("[udp_recv]ip=[%s]port=[%d]\n", senderstr, ntohs(senderinfo.sin_port));
printf("[udp_recv]%s\n", r1_buf);
break;
}
}
close(sock1 );
return 0;
}
// ---------------------------------------------------------
// ---------------------------------------------------------
int main(){
int ret;
ret = udp_send();
if(ret < 0){return -1;}
ret = udp_recv();
if(ret < 0){return -1;}
return 0;
}


トップに戻る