LoginSignup
5
8

More than 5 years have passed since last update.

Windows Console でUDPの送受信

Last updated at Posted at 2016-01-30

minGW を使った、UDPの送受信関数

windows 7 のDOS窓で動作する関数です。

送信側

udpsend.c
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <winsock2.h>

int main(int argc, char** argv)
{
    int sd;
    struct sockaddr_in addr;
    WSADATA wsaData;

    // winsock2の初期化
    WSAStartup(MAKEWORD(2,0), &wsaData);

    //socketシステムコール
    //ディスクリプタsdを取得する
    //SOCK_DGRAM <- UDP, SOCK_STREAM<- TCP
    if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        printf("error:%d\n",WSAGetLastError());
        return -1;
    }

    // 送信先アドレスとポート番号を設定する
    memset(&addr,0,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);   // ポート番号(htons)でネットワークバイトオーダーに変換
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //IPアドレスを格納したin_addr構造体

    // パケットをUDPで送信
    if(sendto(sd, "I am send process", 17, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("sendto");
        printf("error:%d\n",WSAGetLastError());
        return -1;
    }

    printf("send end\n");

    // 接続を切断する
    closesocket(sd);
    WSACleanup();

    return 0;
}

送信側コンパイル

gcc udpsend.c libws2_32.lib

送信側で、送信元のポート番号が欲しい場合、以下を追加

udpsend.c
    //送信元のポート番号が欲しい場合
    struct sockaddr_in sin;
    int addrlen = sizeof(sin);
    if(getsockname(sd, (struct sockaddr *)&sin, &addrlen) == 0 &&
        sin.sin_family == AF_INET && addrlen == sizeof(sin))
    {
        int local_port = ntohs(sin.sin_port);
        printf("send port %s:%d\n",inet_ntoa(sin.sin_addr),local_port);
    }

受信側

udprecv.c
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <winsock.h>
#include <winsock2.h>

int main() 
{
    WSADATA wsaData;
    SOCKET sockfd, new_sockfd;
    int writer_len, recv_len, on;
    struct sockaddr_in reader_addr, writer_addr;
    struct ip_mreq mreq;
    char buf[1024];

    // winsock2の初期化
    WSAStartup(MAKEWORD(1,1), &wsaData);

    //socketシステムコール
    //ディスクリプタsdを取得する
    //SOCK_DGRAM <- UDP, SOCK_STREAM<- TCP
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        printf("error:%d\n",WSAGetLastError());
        return -1;
    }

    /* ファイルディスクリプターで参照されるソケットにオプションの設定 */
    /* SOL_SOCKET : ソケット API 層 */
    /* SO_REUSEADDR : bindが失敗するのを回避 */
    on = 1;
    if (setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) ) == SOCKET_ERROR)
    {
        perror("setsockopt");
        printf("error:%d\n",WSAGetLastError());
        return -1;
    }

    // 受信元アドレスとポート番号を設定する
    memset((char *)&reader_addr, 0, sizeof(reader_addr));
    reader_addr.sin_family = AF_INET;
    reader_addr.sin_addr.s_addr = htonl(INADDR_ANY);    //IPアドレスを格納したin_addr構造体
    reader_addr.sin_port = htons(12345);        // ポート番号(htons)でネットワークバイトオーダーに変換

    // ソケットに名前(ポート番号 & IPアドレス)を付ける
    if (bind(sockfd, (struct sockaddr *)&reader_addr, sizeof(reader_addr)) < 0) {
        perror("bind");
        printf("error:%d\n",WSAGetLastError());
        closesocket(sockfd);
        return -1;
    }

    while(1) {
        //パケットをUDPで受信
        recv_len=recv(sockfd, buf, 1024, 0);
        if(recv_len>0){
            printf("%s\n",buf);
            break;
        }
    }

    // 接続を切断する
    closesocket(sockfd);
    WSACleanup();
}

受信側コンパイル

gcc udpread.c libws2_32.lib

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8