LoginSignup
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

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
What you can do with signing up
8