WebRTC ICE连接与有效的ICE服务器和候选者失败



这是我上一个问题的延续。

我开始使用这个库中的webrtc机箱来创建WebRTC连接,但我遇到了ICE连接失败的问题。我检查了这个网站使用的STUN和TURN服务器,它们都能正常工作。

这是我当前的代码:

async fn new(...) {
let webrtcredux = Arc::new(AsyncMutex::new(WebRtcRedux::default()));
webrtcredux.lock().await.set_tokio_runtime(Handle::current());
let servers = ice.urls.into_iter().map(|url| {
if url.starts_with("turn") {
RTCIceServer {
urls: vec![url],
username: ice.username.clone(),
credential: ice.credential.clone(),
.. RTCIceServer::default()
}
} else {
RTCIceServer {
urls: vec![url],
.. RTCIceServer::default()
}
}
}).collect::<Vec<_>>();
debug!("Using ICE servers: {:#?}", servers);
webrtcredux.lock().await.add_ice_servers(servers);
// More gstreamer setup code...
}
async fn start(...) {
self.pipeline.set_state(gst::State::Playing)?;
let encoder = self.encoder_type;
let arc_from_ws = Arc::new(AsyncMutex::new(from_ws_rx));
self.webrtcredux.lock().await.on_peer_connection_state_change(Box::new(|state| {
debug!("[WebRTC] Peer connection state changed to: {}", state);
Box::pin(async {})
})).await.expect("Failed to set on peer connection state change");
self.webrtcredux.lock().await.on_ice_connection_state_change(Box::new(|state| {
debug!("[WebRTC] ICE connection state changed to: {}", state);
Box::pin(async {})
})).await.expect("Failed to set on ice connection state change");
// let redux_arc = self.webrtcredux.clone();
// let candidates = Arc::new(AsyncMutex::new(Vec::new()));
// let candidates_arc = candidates.clone();
self.webrtcredux.lock().await.on_ice_candidate(Box::new(move |candidate| {
// let redux_arc = redux_arc.clone()
// let candidates = candidates_arc.clone();
Box::pin(async move {
if let Some(candidate) = candidate {
debug!("ICE Candidate: {:#?}", candidate.to_json().await.unwrap());
// candidates.lock().await.push(candidate.to_json().await.unwrap());
}
// redux_arc.lock().await.add_ice_candidate(candidate.unwrap().to_json().await.unwrap()).await.unwrap();
})
})).await.expect("Failed ice candidate");
let redux_arc = self.webrtcredux.clone();
self.webrtcredux.lock().await.on_negotiation_needed(Box::new(move || {
let redux_arc = redux_arc.clone();
info!("[WebRTC] Negotiation needed");
Box::pin(async move {
// Waits for all tracks to be added to create full SDP
redux_arc.lock().await.wait_for_all_tracks().await;
let offer = redux_arc.lock().await.create_offer(Some(RTCOfferOptions {
voice_activity_detection: true,
ice_restart: false,
})).await.expect("Failed to create offer");
// offer.props.insert(4, SdpProp::Attribute {
//     key: "ice-options".to_string(),
//     value: Some("trickle".to_string())
// });
// offer.props.insert(5, SdpProp::Attribute {
//     key: "extmap-allow-mixed".to_string(),
//     value: None
// });
// offer.props.insert(6, SdpProp::Attribute {
//     key: "msid-semantic".to_string(),
//     value: Some(" WMS".to_string())
// });
trace!("[WebRTC] Generated local SDP: {}", offer.to_string());
redux_arc.lock().await.set_local_description(&offer, RTCSdpType::Offer).await.expect("Failed to set local description");
info!("[WebRTC] Local description set");
})
})).await.expect("Failed to set on negotiation needed");
let redux_arc = self.webrtcredux.clone();
self.webrtcredux.lock().await.on_ice_gathering_state_change(Box::new(move |state| {
debug!("[WebRTC] ICE gathering state changed to: {}", state);
let redux_arc = redux_arc.clone();
let to_ws_tx = to_ws_tx.clone();
let from_ws_rx = arc_from_ws.clone();
if state != RTCIceGathererState::Complete {
return Box::pin(async {});
}

Box::pin(async move {
let local = redux_arc.lock().await.local_description().await.unwrap().unwrap();
let video_media: &SdpProp = local.props.iter().find(|v| match *v {
SdpProp::Media { r#type, .. } => {
*r#type == MediaType::Video
},
_ => false
}).unwrap();
let (video_ssrc, video_payload_type, rtx_payload_type) = if let SdpProp::Media { props, .. } = video_media {
let mut ssrc = 0u32;
let mut video_payload = 0u8;
let mut rtx_payload = 0u8;
for prop in props {
match prop {
MediaProp::Attribute { key, value } => {
match key {
v if *v == "rtpmap".to_string() => {
match value {
Some(val) => {
let num = val.clone().split(' ').collect::<Vec<_>>()[0].parse::<u8>().unwrap();
if val.ends_with(&format!("{}/90000", encoder.type_string())) && video_payload == 0 {
video_payload = num;
} else if val.ends_with("rtx/90000") && rtx_payload == 0 {
rtx_payload = num;
}
},
None => unreachable!()
}
},
v if *v == "ssrc".to_string() => {
ssrc = match value {
Some(val) => val.clone().split(' ').collect::<Vec<_>>()[0].parse::<u32>().unwrap(),
None => unreachable!(),
};
},
_ => continue
}
},
_ => continue
}
}
(ssrc, video_payload, rtx_payload)
} else { unreachable!() };
let audio_media: &SdpProp = local.props.iter().find(|v| match *v {
SdpProp::Media { r#type, .. } => {
*r#type == MediaType::Audio
},
_ => false
}).unwrap();
let audio_ssrc = if let SdpProp::Media { props, .. } = audio_media {
props.into_iter().find_map(|p| match p {
MediaProp::Attribute {key, value} => {
if key != "ssrc" {
return None;
}
let val = match value {
Some(val) => val.clone(),
None => unreachable!(),
};
Some(val.split(' ').collect::<Vec<_>>()[0].parse::<u32>().unwrap())
},
_ => None
}).unwrap()
} else { unreachable!() };
trace!("[WebRTC] Updated local SDP: {}", local.to_string());
to_ws_tx.send(ToWs {
ssrcs: StreamSSRCs {
audio: audio_ssrc,
video: video_ssrc,
rtx: 0
},
local_sdp: local.to_string(),
video_payload_type,
rtx_payload_type,
}).await.unwrap();
let from_ws = from_ws_rx.lock().await.recv().await.unwrap();
match SDP::from_str(&from_ws.remote_sdp).unwrap().props.pop().unwrap() {
SdpProp::Media { ports, props, .. } => {
let mut main_ip = None;
let mut fingerprint = None;
let mut ufrag = None;
let mut pwd = None;
let mut candidate = None;
for prop in props {
let current = prop.clone();
match prop {
MediaProp::Connection { address, .. } => main_ip = Some(address),
MediaProp::Attribute { key, value: _ } => {
match &key[..] {
"candidate" => candidate = Some(current),
"fingerprint" => fingerprint = Some(current),
"ice-ufrag" => ufrag = Some(current),
"ice-pwd" => pwd = Some(current),
_ => continue
}
}
_ => continue
}
}
let connection = MediaProp::Connection {
net_type: NetworkType::Internet,
address_type: AddressType::IPv4,
address: main_ip.unwrap(),
ttl: Some(127),
num_addresses: Some(1),
suffix: None,
};
let base_media_props = vec![
connection,
// candidate.unwrap(),
fingerprint.unwrap(),
ufrag.unwrap(),
pwd.unwrap(),
MediaProp::Attribute {
key: "rtcp-mux".to_string(),
value: None
},
MediaProp::Attribute {
key: "rtcp".to_string(),
value: Some(ports[0].to_string())
},
MediaProp::Attribute {
key: "setup".to_string(),
value: Some("passive".to_string())
},
MediaProp::Attribute {
key: "inactive".to_string(),
value: None
}
];
let mut video_vec_attrs = ["ccm fir", "nack", "nack pli", "goog-remb", "transport-cc"].into_iter().map(|val| {
MediaProp::Attribute {
key: "rtcp-fb".to_string(),
value: Some(format!("{} {}", video_payload_type, val))
}
}).collect::<Vec<_>>();
video_vec_attrs.append(&mut [
"2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", 
"3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
"14 urn:ietf:params:rtp-hdrext:toffset",
"13 urn:3gpp:video-orientation",
"5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay"
].into_iter().map(|ext| {
MediaProp::Attribute {
key: "extmap".to_string(),
value: Some(ext.to_string())
}
}).collect::<Vec<_>>());
video_vec_attrs.append(&mut vec![
MediaProp::Attribute { 
key: "fmtp".to_string(), 
value: Some(format!("{} x-google-max-bitrate=2500;level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", video_payload_type))
},
MediaProp::Attribute {
key: "fmtp".to_string(),
value: Some(format!("{} apt={}", rtx_payload_type, video_payload_type))
},
MediaProp::Attribute {
key: "mid".to_string(),
value: Some(0.to_string())
},
MediaProp::Attribute {
key: "rtpmap".to_string(),
value: Some(format!("{} {}/90000", video_payload_type, encoder.type_string()))
},
MediaProp::Attribute {
key: "rtpmap".to_string(),
value: Some(format!("{} rtx/90000", rtx_payload_type))
},
candidate.unwrap(),
MediaProp::Attribute {
key: "end-of-candidates".to_string(),
value: None
}
]);
let video_media = SdpProp::Media {
r#type: MediaType::Video,
ports: ports.clone(),
protocol: format!("UDP/TLS/RTP/SAVPF {} {}", video_payload_type, rtx_payload_type),
format: "".to_string(),
props: base_media_props.clone().into_iter().chain(video_vec_attrs.into_iter()).collect::<Vec<_>>()
};
let mut audio_vec_attrs = [
"1 urn:ietf:params:rtp-hdrext:ssrc-audio-level", 
"3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
].into_iter().map(|ext| {
MediaProp::Attribute {
key: "extmap".to_string(),
value: Some(ext.to_string())
}
}).collect::<Vec<_>>();
audio_vec_attrs.append(&mut vec![
MediaProp::Attribute {
key: "fmtp".to_string(),
value: Some("111 minptime=10;useinbandfec=1;usedtx=1".to_string())
},
MediaProp::Attribute {
key: "maxptime".to_string(),
value: Some(60.to_string())
},
MediaProp::Attribute {
key: "rtpmap".to_string(),
value: Some("111 opus/90000".to_string())
},
MediaProp::Attribute {
key: "rtcp-fb".to_string(),
value: Some("111 transport-cc".to_string())
},
MediaProp::Attribute {
key: "mid".to_string(),
value: Some(1.to_string())
}
]);
let audio_media = SdpProp::Media {
r#type: MediaType::Audio,
ports,
protocol: "UDP/TLS/RTP/SAVPF 111".to_string(),
format: "".to_string(),
props: base_media_props.clone().into_iter().chain(audio_vec_attrs.into_iter()).collect::<Vec<_>>()
};
// Generate answer
let answer = SDP { props: vec![
SdpProp::Version(0),
SdpProp::Origin { 
username: "-".to_string(), 
session_id: "1420070400000".to_string(), 
session_version: 0, 
net_type: NetworkType::Internet, 
address_type: AddressType::IPv4, 
address: "127.0.0.1".to_string() 
},
SdpProp::SessionName("-".to_string()),
SdpProp::Timing {
start: 0,
stop: 0
},
SdpProp::Attribute {
key: "msid-semantic".to_string(),
value: Some(" WMS *".to_string())
},
SdpProp::Attribute {
key: "group".to_string(),
value: Some("BUNDLE 0 1".to_string())
},
video_media,
audio_media
]};
trace!("[WebRTC] Generated remote SDP: {}", answer.to_string());
redux_arc.lock().await.set_remote_description(&answer, RTCSdpType::Answer).await.expect("Failed to set remote description");
info!("[WebRTC] Remote description set");
}
_ => unreachable!()
}
})
})).await.expect("Failed to set on ice gathering change");
Ok(StateChangeSuccess::Success)
}

ICE收集完成后的本地SDP:

v=0
o=- 3006164469565782471 253007078 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 F5:34:75:08:3E:AB:99:1E:5F:79:BF:6D:14:EC:D6:C2:F6:20:74:D6:D3:1D:78:48:58:B6:1E:2B:32:F3:D9:64
a=group:BUNDLE 0 1
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 123 118 116
c=IN IP4 0.0.0.0
a=setup:actpass
a=mid:0
a=ice-ufrag:cWRCBPTiuOohkLsf
a=ice-pwd:mHMqXcRexKOkbHKAZlvxjgvLFtdHiZAL
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtcp-fb:96 transport-cc
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 transport-cc
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 transport-cc
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtcp-fb:99 nack
a=rtcp-fb:99 nack pli
a=rtcp-fb:99 transport-cc
a=rtpmap:100 VP9/90000
a=fmtp:100 profile-id=1
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 transport-cc
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 transport-cc
a=rtpmap:102 H264/90000
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=rtcp-fb:102 transport-cc
a=rtpmap:121 rtx/90000
a=fmtp:121 apt=102
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 transport-cc
a=rtpmap:127 H264/90000
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 transport-cc
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 transport-cc
a=rtpmap:125 H264/90000
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=rtcp-fb:125 transport-cc
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 transport-cc
a=rtpmap:108 H264/90000
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=rtcp-fb:108 transport-cc
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtcp-fb:109 nack
a=rtcp-fb:109 nack pli
a=rtcp-fb:109 transport-cc
a=rtpmap:123 H264/90000
a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
a=rtcp-fb:123 goog-remb
a=rtcp-fb:123 ccm fir
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=rtcp-fb:123 transport-cc
a=rtpmap:118 rtx/90000
a=fmtp:118 apt=123
a=rtcp-fb:118 nack
a=rtcp-fb:118 nack pli
a=rtcp-fb:118 transport-cc
a=rtpmap:116 ulpfec/90000
a=rtcp-fb:116 nack
a=rtcp-fb:116 nack pli
a=rtcp-fb:116 transport-cc
a=extmap:1 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=ssrc:3980097584 cname:video_0
a=ssrc:3980097584 msid:video_0 video
a=ssrc:3980097584 mslabel:video_0
a=ssrc:3980097584 label:video
a=msid:video_0 video
a=sendrecv
a=candidate:167090039 1 udp 2130706431 :: 48818 typ host
a=candidate:167090039 2 udp 2130706431 :: 48818 typ host
a=candidate:2938512866 1 udp 2130706431 192.168.1.100 47953 typ host
a=candidate:2938512866 2 udp 2130706431 192.168.1.100 47953 typ host
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 35989 typ srflx raddr 0.0.0.0 rport 35989
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 35989 typ srflx raddr 0.0.0.0 rport 35989
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 37580 typ srflx raddr 0.0.0.0 rport 37580
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 37580 typ srflx raddr 0.0.0.0 rport 37580
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 59238 typ srflx raddr 0.0.0.0 rport 59238
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 59238 typ srflx raddr 0.0.0.0 rport 59238
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 53377 typ srflx raddr 0.0.0.0 rport 53377
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 53377 typ srflx raddr 0.0.0.0 rport 53377
a=candidate:1022905401 1 udp 16777215 34.203.251.215 29290 typ relay raddr 0.0.0.0 rport 38594
a=candidate:1022905401 2 udp 16777215 34.203.251.215 29290 typ relay raddr 0.0.0.0 rport 38594
a=end-of-candidates
m=audio 9 UDP/TLS/RTP/SAVPF 111 9 0 8
c=IN IP4 0.0.0.0
a=setup:actpass
a=mid:1
a=ice-ufrag:cWRCBPTiuOohkLsf
a=ice-pwd:mHMqXcRexKOkbHKAZlvxjgvLFtdHiZAL
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=rtpmap:9 G722/8000
a=rtcp-fb:9 transport-cc
a=rtpmap:0 PCMU/8000
a=rtcp-fb:0 transport-cc
a=rtpmap:8 PCMA/8000
a=rtcp-fb:8 transport-cc
a=extmap:1 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=ssrc:597106938 cname:audio_0
a=ssrc:597106938 msid:audio_0 audio
a=ssrc:597106938 mslabel:audio_0
a=ssrc:597106938 label:audio
a=msid:audio_0 audio
a=sendrecv

生成的远程SDP:

v=0
o=- 1420070400000 0 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic: WMS *
a=group:BUNDLE 0 1
m=video 50016 UDP/TLS/RTP/SAVPF 98 97 
c=IN IP4 66.22.231.190/127/1
a=fingerprint:sha-256 4A:79:94:16:44:3F:BD:05:41:5A:C7:20:F3:12:54:70:00:73:5D:33:00:2D:2C:80:9B:39:E1:9F:2D:A7:49:87
a=ice-ufrag:PkLE
a=ice-pwd:o9QGn2N6YizFOM/UNojYai
a=rtcp-mux
a=rtcp:50016
a=setup:passive
a=inactive
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:13 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=fmtp:98 x-google-max-bitrate=2500;level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=fmtp:97 apt=98
a=mid:0
a=rtpmap:98 VP9/90000
a=rtpmap:97 rtx/90000
a=candidate:1 1 UDP 4261412862 66.22.231.190 50016 typ host
a=end-of-candidates
m=audio 50016 UDP/TLS/RTP/SAVPF 111 
c=IN IP4 66.22.231.190/127/1
a=fingerprint:sha-256 4A:79:94:16:44:3F:BD:05:41:5A:C7:20:F3:12:54:70:00:73:5D:33:00:2D:2C:80:9B:39:E1:9F:2D:A7:49:87
a=ice-ufrag:PkLE
a=ice-pwd:o9QGn2N6YizFOM/UNojYai
a=rtcp-mux
a=rtcp:50016
a=setup:passive
a=inactive
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=fmtp:111 minptime=10;useinbandfec=1;usedtx=1
a=maxptime:60
a=rtpmap:111 opus/90000
a=rtcp-fb:111 transport-cc
a=mid:1

在设置远程应答SDP之后,ICE连接状态变为"0";"检查";,但在大约20秒后它变为"0";失败";并终止连接。在SDP或代码方面,我是否做错了什么?

编辑:我开始记录了,这是连接日志:https://pastebin.com/vNvd3Af6

编辑2:我没有接收到来自STUN服务器的任何入站流量。使用相同ICE服务器的其他程序运行良好,那么在基本网络配置之外,我会做错什么呢?

编辑3:这是一个正在工作的ICE连接捕获,这是我目前正在处理的一个。

编辑4:我运行了netstat来查看我的代码正在侦听哪些端口,并且存在一些差异。我删掉了所有其他节目。

这是正在工作的ICE连接:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name         
tcp        0      0 192.168.1.100:41383     0.0.0.0:*               LISTEN      37973/target/debug/ 
tcp        0      0 192.168.1.100:51469     0.0.0.0:*               LISTEN      37973/target/debug/ 
tcp6       0      0 fe80::60d2:bcaa:a:40899 :::*                    LISTEN      37973/target/debug/        
udp        0      0 192.168.1.100:44897     0.0.0.0:*                           37973/target/debug/      
udp        0      0 239.255.255.250:1900    0.0.0.0:*                           37973/target/debug/ 
udp        0      0 192.168.1.100:1900      0.0.0.0:*                           37973/target/debug/ 
udp        0      0 239.255.255.250:1900    0.0.0.0:*                           37973/target/debug/ 
udp        0      0 127.0.0.1:1900          0.0.0.0:*                           37973/target/debug/ 
udp        0      0 127.0.0.1:37386         0.0.0.0:*                           37973/target/debug/      
udp        0      0 192.168.1.100:59877     0.0.0.0:*                           37973/target/debug/ 
udp6       0      0 fe80::60d2:bcaa:a:56003 :::*                                37973/target/debug/

这是不工作的连接:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name          
udp        0      0 0.0.0.0:50651           0.0.0.0:*                           37186/target/debug/      
udp        0      0 0.0.0.0:51996           0.0.0.0:*                           37186/target/debug/ 
udp        0      0 0.0.0.0:35776           0.0.0.0:*                           37186/target/debug/ 
udp        0      0 0.0.0.0:53036           0.0.0.0:*                           37186/target/debug/ 
udp        0      0 224.0.0.251:5353        0.0.0.0:*                           37186/target/debug/ 
udp        0      0 0.0.0.0:40115           0.0.0.0:*                           37186/target/debug/ 
udp        0      0 192.168.1.100:40707     0.0.0.0:*                           37186/target/debug/        
udp6       0      0 :::37965                :::*                                37186/target/debug/ 

当我在新实现中发送CRLF时,我与之通信的服务器只接受LF行结尾。将其更改为LF解决了问题。

最新更新