c语言 - Winsock - 为什么ZNC(和IRC保镖)不接受我的Winsock连接?



使用典型的 irc 客户端,我可以输入:

/server localhost 6667 nick:pass

当我输入我为 ZNC(一个 IRC 保镖)配置的 nick:pass 时,我被转发到我的服务器/nick:pass 组合下 znc 连接到的服务器。

如何以编程方式同时打开与所有这些参数的 winsock 连接? /server localhost 6667 nick:pass

我尝试在连接后发送数据,但 znc 似乎忽略了这些请求。或者我只是根本没有连接到它。这段代码已经连接到一个不需要Ping身份验证的IRC服务器,所以我知道它有效。

#define AF_INET                    2
#define SOCK_STREAM                1
#define SOL_SOCKET                 0xffff
#define SO_SNDTIMEO                0x1005
string server_addr = "127.0.0.1";
int server_port = 6667;
void ircconnect(){
int struct_sockaddr[4];
int addr, port_low, port_high;
int opts[1];
int c;
if (irc_disabled == 1) return(0);
// fill the sockaddr struct
addr = inet_addr(server_addr);
port_low = server_port & 0x00ff;
port_high = (server_port & 0xff00) >> 8; 
struct_sockaddr[0] = AF_INET | (port_high << 16) | (port_low << 24);
struct_sockaddr[1] = addr;
struct_sockaddr[2] = 0;
struct_sockaddr[3] = 0;
// connect
s = socket(AF_INET, SOCK_STREAM, 0);
opts[0] = 1000; // send timeout milliseconds
setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, opts, 4);
c = connect(s, struct_sockaddr, 16);
Sleep(5000);
sendLine(nick + ":" + password);

请参阅下面的python解释:

int struct_sockaddr[4];
int addr, port_low, port_high;
int opts[1];
int c;
string zncauth = nick + ":" + password;
if (irc_disabled == 1) return(0);
// fill the sockaddr struct
addr = inet_addr(server_addr);
port_low = server_port & 0x00ff;
port_high = (server_port & 0xff00) >> 8; 
struct_sockaddr[0] = AF_INET | (port_high << 16) | (port_low << 24);
struct_sockaddr[1] = addr;
struct_sockaddr[2] = 0;
struct_sockaddr[3] = 0;
// connect
s = socket(AF_INET, SOCK_STREAM, 0);
opts[0] = 1000; // send timeout milliseconds
setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, opts, 4);
c = connect(s, struct_sockaddr, 16);
// send
sendLine("NICK zncbotnick");
sendLine("USER znc bot znc :znc");
sendLine("PASS " + zncauth);
void sendLine(string text){
    if (irc_disabled == 1) return(0);
    text = text + "rn";
    send(s, text, StringLen(text), 0);
}

上面的代码终于起作用了,这对我在python中可以使用ZNC进行身份验证。基本上,在另一种语言中,我向 znc 抛出命令,但他们从未到达 znc,因为代码缺少返回符和换行符'rn'。使用python,我能够实时诊断问题。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
//Test.py
import socket
zncauth = 'nick:password'
server_addr = '127.0.0.1'
server_port = 6667
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((server_addr, server_port))   
s.send( 'NICK botnickrn')
s.send( 'USER znc bot znc :zncrn')
s.send( 'PASS ' + zncauth + ' rn')

使用像 Wireshark 这样的数据包嗅探器查看使用 IRC 客户端连接到 ZNC 时的套接字流量与代码,并查找发送的命令中的任何差异。

话虽如此,您的代码中也有一些奇怪之处。 试试这个:

#define AF_INET                    2
#define SOCK_STREAM                1
#define SOL_SOCKET                 0xffff
#define SO_SNDTIMEO                0x1005
string server_addr = "127.0.0.1";
u_short server_port = 6667;
void ircconnect(){
    struct sockaddr_in addr;
    int opts;
    int c;
    if (irc_disabled == 1) return(0);
    // fill the sockaddr struct
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(server_port);
    addr.sin_addr.s_addr = inet_addr(server_addr.c_str());
    // connect
    s = socket(AF_INET, SOCK_STREAM, 0);
    opts = 1000; // send timeout milliseconds
    setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&opts, sizeof(opts));
    c = connect(s, (struct sockaddr *)&addr, sizeof(addr));
    Sleep(5000);
    sendLine(nick + ":" + password);

IRC服务器实现了Internet Relay Chat协议。

该协议与您在 IRC 客户端中键入的命令没有任何共同之处。 由于您不尊重 IRC 协议,服务器无法理解您在说什么,因此充其量会忽略您,或者只是断开连接。

该协议在一组 4 个 RFC 中定义:RFC2810、RFC2811、RFC2812 和 RFC2813。

在尝试实现任何将与IRC服务器交互的程序之前,您应该阅读这些文档并了解IRC架构和procotol。

此外,您将轻松找到一些为您实现协议的库。

最新更新