XMPP를 통해 내 애플리케이션에 Facebook 채팅을 통합 할 수 있도록 Facebook X_FACEBOOK_PLATFORM SASL 메커니즘을 구현하려고합니다. 나는 그것이 작동 여부 (내 SASL 구현을 생각하기 때문에, 나는 그것을 테스트 할 기회가 없었어요,명백한 이유없이 소켓 연결이 닫힙니다.
var ak = "my app id";
var sk = "access token";
var aps = "my app secret";
using (var client = new TcpClient())
{
client.Connect("chat.facebook.com", 5222);
using (var writer = new StreamWriter(client.GetStream())) using (var reader = new StreamReader(client.GetStream()))
{
// Write for the first time
writer.Write("<stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" to=\"chat.facebook.com\"><auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-FACEBOOK-PLATFORM\" /></stream:stream>");
writer.Flush();
Thread.Sleep(500);
// I am pretty sure following works or at least it's not what causes the error
var challenge = Encoding.UTF8.GetString(Convert.FromBase64String(XElement.Parse(reader.ReadToEnd()).Elements().Last().Value)).Split('&').Select(s => s.Split('=')).ToDictionary(s => s[0], s => s[1]);
var response = new SortedDictionary<string, string>() { { "api_key", ak }, { "call_id", DateTime.Now.Ticks.ToString() }, { "method", challenge["method"] }, { "nonce", challenge["nonce"] }, { "session_key", sk }, { "v", "1.0" } };
var responseString1 = string.Format("{0}{1}", string.Join(string.Empty, response.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()), aps);
byte[] hashedResponse1 = null;
using (var prov = new MD5CryptoServiceProvider()) hashedResponse1 = prov.ComputeHash(Encoding.UTF8.GetBytes(responseString1));
var builder = new StringBuilder();
foreach (var item in hashedResponse1) builder.Append(item.ToString("x2"));
var responseString2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}&sig={1}", string.Join("&", response.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()), builder.ToString().ToLower()))); ;
// Write for the second time
writer.Write(string.Format("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">{0}</response>", responseString2));
writer.Flush();
Thread.Sleep(500);
MessageBox.Show(reader.ReadToEnd());
}
}
I 단축하고 가능한 한 많은 코드를 축소 : 여기
코드입니다 아직) 오류의 원인이 아닙니다.다음과 같은 예외가 내 얼굴에 나타납니다. 전송 연결에서 데이터를 읽을 수 없습니다. 설정된 연결이 호스트 시스템의 소프트웨어에 의해 중단되었습니다. 는
그것은 내가 두 번째로 client
의 스트림에서 읽으려고 할 때마다 발생을 System.Net.Sockets.SocketError.ConnectionAborted. 보시다시피 페이스 북 서버가 나에게 응답 할 충분한 시간을 갖기 위해 여기에 스레드를 일시 중지하는 것을 볼 수 있겠지만, 전에 비동기 접근법을 사용했고 똑같은 문제가 발생했습니다. 그래서 동기식으로 먼저 시도하기로 결정했습니다. 어쨌든 실제 SASL 메커니즘 구현은 실제로 발생하지 않아야합니다. 바로 인증을 시도하지 않으면 서버가 사용하는 메커니즘을 확인하고 읽기 및 쓰기의 다른 라운드에서 해당 메커니즘을 선택하라는 요청을 보내므로 실패합니다. 내가 바로 메커니즘 선택 XML을 보낼 때, 그것은 작동하고 어떤 초에 보내는데 실패합니다.
그래서 결론은 다음과 같습니다. 나는 소켓 연결을 열고, 거기에서 읽고 (첫 번째 읽기는 동기화와 비동기 모두 작동 함), 두 번째로 쓰고 두 번째로 읽으려고합니다. 여기에서는 항상 실패합니다. 분명히 문제는 소켓 연결 그 자체입니다. 두 번째 읽기에는 새로운 StreamReader
을 사용하려고했지만 아무 소용이 없습니다. "수신 된"이벤트 또는 Send(string data, Action<string> responseProcessor)
과 같은 외관을 구현하여 해당 스트림에 대한 작업을 편안하게하고 싶습니다. 구현이 이미 있었지만 두 번째 읽기에도 실패했습니다.
의견을 보내 주셔서 감사합니다.
편집 : 다음은 NetworkStream의 facade 코드입니다. 이 비동기 방식을 사용할 때도 같은 일이 발생하지만 몇 시간 전에는 작동했지만 두 번째 응답에서는 첫 번째 응답과 동일한 문자열이 반환되었습니다. 그 동안 내가 무엇을 바꿨는지, 어떻게 바꿀 수는없는 것입니다.
public void Send(XElement fragment)
{
if (Sent != null) Sent(this, new XmppEventArgs(fragment));
byte[] buffer = new byte[1024];
AsyncCallback callback = null;
callback = (a) =>
{
var available = NetworkStream.EndRead(a);
if (available > 0)
{
StringBuilder.Append(Encoding.UTF8.GetString(buffer, 0, available));
NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
}
else
{
var args = new XmppEventArgs(XElement.Parse(StringBuilder.ToString()));
if (Received != null) Received(this, args);
StringBuilder = new StringBuilder();
// NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
}
};
NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
NetworkStreamWriter.Write(fragment);
NetworkStreamWriter.Flush();
}
답변 주셔서 감사합니다. 결국 StreamReader 및 StreamWriter를 사용하는 대신 NetworkStream.Read 및 NetworkStream에 간단한 쓰기로 돌아가서이 문제가 해결되었습니다. 그러나 평소와 같이 두 가지 새로운 것이 튀어 나왔습니다. 그래서 재미는 아직 끝나지 않았습니다. 어쨌든 당신의 대답에 감사드립니다! –