質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

3057閲覧

Swift3 UDP Client 指定ipにデータの送信ができない

hyu_sy

総合スコア7

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/11/09 17:12

編集2017/11/13 01:57

###前提・実現したいこと
iOSの携帯端末で動作するSwift3のプロジェクトにおいて
UDP方式でテキストを送信する単純なプログラムを書いています

###発生している問題・エラーメッセージ

sockaddr_in から unsafePointer<sockaddr> の変換でかなり躓き
なんとかエラーなくsendto()に収めることができましたが
PC側でデータの受信ができません

###該当のソースコード
//sockaddr_inを作る関数

func getaddrinfo( address: String, port: CUnsignedShort) -> sockaddr_in{ let ipOcts = address.components(separatedBy: ".") let ipInt = ipOcts.enumerated().reduce(UInt32(0)){ (val, elm) in let u32 = UInt32(elm.element)! let shiftBits = 24 - UInt32(elm.offset) * 8 return val | (u32 << shiftBits) } return sockaddr_in( sin_len: UInt8(MemoryLayout<sockaddr_in>.stride), sin_family: UInt8(AF_INET), sin_port: port.bigEndian, sin_addr: in_addr(s_addr: ipInt), sin_zero: ( 0, 0, 0, 0, 0, 0, 0, 0 ) ) } func udpSend(textToSend: String, address: String, port: CUnsignedShort) { let fd = socket(AF_INET, SOCK_DGRAM, 0) // DGRAM makes it UDP var sendtext = textToSend var addr = getaddrinfo(address: address, port: port) withUnsafeMutablePointer(to: &sendtext) { textp in let cstr = UnsafeRawPointer(textp) withUnsafePointer(to: &addr){sockaddrInPtr in sockaddrInPtr.withMemoryRebound(to: sockaddr.self, capacity: 1){ sockaddrPtr in let check = sendto(fd, cstr, Int(strlen(sendtext)), 0, sockaddrPtr , socklen_t(MemoryLayout<sockaddr>.stride)) print(check) } } }

###試したこと
バージョンに適したunsafePointer系の取り扱い
###補足情報(言語/FW/ツール等のバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MasakiHori

2017/11/10 09:28

とりあえず、 sendtoの戻り値を調べて-1の時はerrnoを出力するようにすればどうでしょう?  あと、getaddrinfo関数を使ってないのが奇妙に思えます。
hyu_sy

2017/11/13 02:04

戻り値が正常値だったのですが、相変わらず受信ができません 受信確認用ソフトウェアはwindows対応フリーソフトにて行っております HASCのiOS対応アプリケーションによるUDP送信は確認しているため、受信側の問題ではないと思います   質問をする以上可読性を意識するべきでした 今後、関数化のように可読性を意識して書いていこうと思います また、早い回答をいただいたのにも関わらず返事が遅く申し訳ありません どうぞご指導お願いいたします
guest

回答2

0

T_obaraさんありがとうございます。
ipアドレスの格納についての知見が足りていませんでした。
指導いただいたbig endianの方法と一般的なinet_addrの手法で受信を確認できました。

また、投稿したプログラムではstring型の送信に失敗していたので修正しました。

func udpSend(textToSend: String, address: String, port: CUnsignedShort) { let fd = socket(AF_INET, SOCK_DGRAM, 0) // DGRAM makes it UDP var addr = getaddrinfo(address: address, port:port) textToSend.withCString{ cstr -> Void in withUnsafePointer(to: &addr){sockaddrInPtr in sockaddrInPtr.withMemoryRebound(to: sockaddr.self, capacity: 1){ sockaddrPtr in let check = sendto(fd, cstr, Int(strlen(sendtext)), 0, sockaddrPtr , socklen_t(MemoryLayout<sockaddr>.stride)) print(check) } } }

投稿2017/11/23 05:07

hyu_sy

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

swift

1sin_addr: in_addr(s_addr: ipInt),

この行ですが、アドレスについてもネットワークバイトオーダーにする必要があります。
ipIntをipInt.bigEndian にするのが手っ取り早いですが、通常inet_addrを利用するのが良いかと思います。

swift

1 2extension String { 3 var utf8CString: UnsafePointer<Int8> { 4 return UnsafePointer((self as NSString).utf8String!) 5 } 6} 7 8addr.sin_addr.s_addr = inet_addr(address.utf8CString) 9

投稿2017/11/22 06:31

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問