如何使用 C 中的套接字将客户端连接到 IRC 服务器
How to connect a client to an IRC server using sockets in C
我正在编写一个要连接到 irc.hackerzvoice.net 的 IRC 客户端。
我已阅读 RFC1459 以及 Whosebug 上的类似帖子,但仍未了解我的代码中可能存在的错误。
发送 NICK 和 USER 消息后,我仍然收到相同的“注册超时”错误。
La socket 280 est ouverte en TCP/IP.
Connexion a 212.83.153.145 sur le port 6667
68 octets ont ete recus
texte recu : :irc.hackerzvoice.net NOTICE Auth :*** Looking up your hostname...
16 octets envoyes au serveur
texte envoye : NICK parallel
.30 octets envoyes au serveur
texte envoye : USER parallel * * :parallel
.99 octets ont ete recus
texte recu : :irc.hackerzvoice.net NOTICE Auth :*** Found your hostname (catv-89-132-88-100.catv.broadband.hu)
92 octets ont ete recus
texte recu : ERROR :Closing link: (unknown@catv-89-132-88-100.catv.broadband.hu) [Registration timeout]
d.hu)
0 octets ont ete recus
texte recu : ERROR :Closing link: (unknown@catv-89-132-88-100.catv.broadband.hu) [Registration timeout]
d.hu)
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "root_me_1.h"
int main()
{
// Si la plateforme est Windows
#if defined (WIN32)
WSADATA WSAData;
WSAStartup(MAKEWORD(2,2), &WSAData); // sert à initialiser la bibliothèque WinSock
#endif
// socket et interface de connexion
SOCKET sock;
SOCKADDR_IN sin; // structure
char buffer[TAILLE_MAX] = "";
int nOctetsRecus = 0;
int nOctetsEnvoyes = 0;
int tailleBuffer = 0;
int boucle = 1;
// on crée une socket utilisant protocole TCP/IP
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
printf("Erreur, socket non valide");
printf("La socket %d est ouverte en TCP/IP.\n", sock);
// on configure l'interface de connexion
sin.sin_addr.s_addr = inet_addr("212.83.153.145"); // adresse IP du serveur IRC
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT); // sin_port et sin_addr doivent être en Network Byte Order // htons() convertit un entier court depuis l'ordre des octets de l'hôte vers celuidu réseau (host to network short)
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR) // si le client réussit à se connecter au serveur
printf("Connexion a %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
else
printf("Erreur de connexion.");
// on reçoit les données envoyées par le serveur
nOctetsRecus = recv(sock, buffer, TAILLE_MAX, 0);
if(nOctetsRecus != SOCKET_ERROR)
{
printf("%d octets ont ete recus\n", nOctetsRecus);
printf("texte recu : %s", buffer);
}
else
printf("Les donnees n'ont pas ete recues");
// le client envoie des données au serveur
sprintf(buffer, "NICK parallel\r\n");
tailleBuffer = strlen(buffer)+1; // taille de la chaine + '[=11=]'
nOctetsEnvoyes = send(sock, buffer, tailleBuffer, 0);
if(nOctetsEnvoyes != SOCKET_ERROR)
{
printf("%d octets envoyes au serveur\n", nOctetsEnvoyes);
printf("texte envoye : %s", buffer);
}
else
printf("Erreur : donnees non envoyees au serveur");
// le client envoie des données au serveur
sprintf(buffer, "USER parallel * * :parallel\r\n");
tailleBuffer = strlen(buffer)+1; // taille de la chaine + '[=11=]'
nOctetsEnvoyes = send(sock, buffer, tailleBuffer, 0);
if(nOctetsEnvoyes != SOCKET_ERROR)
{
printf("%d octets envoyes au serveur\n", nOctetsEnvoyes);
printf("texte envoye : %s", buffer);
}
else
printf("Erreur : donnees non envoyees au serveur");
// on reçoit les données envoyées par le serveur
nOctetsRecus = recv(sock, buffer, TAILLE_MAX, 0);
if(nOctetsRecus != SOCKET_ERROR)
{
printf("%d octets ont ete recus\n", nOctetsRecus);
printf("texte recu : %s", buffer);
}
else
printf("Les donnees n'ont pas ete recues");
// on ferme la connexion
closesocket(sock);
#if defined (WIN32)
WSACleanup(); // libère les ressources allouées par la fonction WSAStartup()
#endif
getchar();
return EXIT_SUCCESS;
}
你知道这个问题吗?
谢谢。
就是这个问题,
sprintf(buffer, "NICK hoeplem\r\n");
tailleBuffer = strlen(buffer)+1;
因为strlen(buffer) + 1
少了一个字节(不应将null
终止符'[=14=]'
发送到服务器并且strlen()
returns 字符串的 length 不包括 null
终止符。) 字符串的实际长度。如果服务器读取该字节,它可能期望 '\r\n'
刷新缓冲区并处理命令,因此它在最后一个“命令”之后永远等待。
应该是
tailleBuffer = sprintf(buffer, "NICK hoeplem\r\n");
这样就完美了。
您可能还想检查 POSIX's dprintf()
and/or 滚动自己的 dprintf()
以避免每次都 sprintf()
ing。
此外,最好将每个命令作为一个带有参数的函数,并为每个可能的命令简单地调用 command_X(sock, PARAMETERS ...)
,这样您的代码会更健壮。
我正在编写一个要连接到 irc.hackerzvoice.net 的 IRC 客户端。 我已阅读 RFC1459 以及 Whosebug 上的类似帖子,但仍未了解我的代码中可能存在的错误。 发送 NICK 和 USER 消息后,我仍然收到相同的“注册超时”错误。
La socket 280 est ouverte en TCP/IP.
Connexion a 212.83.153.145 sur le port 6667
68 octets ont ete recus
texte recu : :irc.hackerzvoice.net NOTICE Auth :*** Looking up your hostname...
16 octets envoyes au serveur
texte envoye : NICK parallel
.30 octets envoyes au serveur
texte envoye : USER parallel * * :parallel
.99 octets ont ete recus
texte recu : :irc.hackerzvoice.net NOTICE Auth :*** Found your hostname (catv-89-132-88-100.catv.broadband.hu)
92 octets ont ete recus
texte recu : ERROR :Closing link: (unknown@catv-89-132-88-100.catv.broadband.hu) [Registration timeout]
d.hu)
0 octets ont ete recus
texte recu : ERROR :Closing link: (unknown@catv-89-132-88-100.catv.broadband.hu) [Registration timeout]
d.hu)
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "root_me_1.h"
int main()
{
// Si la plateforme est Windows
#if defined (WIN32)
WSADATA WSAData;
WSAStartup(MAKEWORD(2,2), &WSAData); // sert à initialiser la bibliothèque WinSock
#endif
// socket et interface de connexion
SOCKET sock;
SOCKADDR_IN sin; // structure
char buffer[TAILLE_MAX] = "";
int nOctetsRecus = 0;
int nOctetsEnvoyes = 0;
int tailleBuffer = 0;
int boucle = 1;
// on crée une socket utilisant protocole TCP/IP
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
printf("Erreur, socket non valide");
printf("La socket %d est ouverte en TCP/IP.\n", sock);
// on configure l'interface de connexion
sin.sin_addr.s_addr = inet_addr("212.83.153.145"); // adresse IP du serveur IRC
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT); // sin_port et sin_addr doivent être en Network Byte Order // htons() convertit un entier court depuis l'ordre des octets de l'hôte vers celuidu réseau (host to network short)
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR) // si le client réussit à se connecter au serveur
printf("Connexion a %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
else
printf("Erreur de connexion.");
// on reçoit les données envoyées par le serveur
nOctetsRecus = recv(sock, buffer, TAILLE_MAX, 0);
if(nOctetsRecus != SOCKET_ERROR)
{
printf("%d octets ont ete recus\n", nOctetsRecus);
printf("texte recu : %s", buffer);
}
else
printf("Les donnees n'ont pas ete recues");
// le client envoie des données au serveur
sprintf(buffer, "NICK parallel\r\n");
tailleBuffer = strlen(buffer)+1; // taille de la chaine + '[=11=]'
nOctetsEnvoyes = send(sock, buffer, tailleBuffer, 0);
if(nOctetsEnvoyes != SOCKET_ERROR)
{
printf("%d octets envoyes au serveur\n", nOctetsEnvoyes);
printf("texte envoye : %s", buffer);
}
else
printf("Erreur : donnees non envoyees au serveur");
// le client envoie des données au serveur
sprintf(buffer, "USER parallel * * :parallel\r\n");
tailleBuffer = strlen(buffer)+1; // taille de la chaine + '[=11=]'
nOctetsEnvoyes = send(sock, buffer, tailleBuffer, 0);
if(nOctetsEnvoyes != SOCKET_ERROR)
{
printf("%d octets envoyes au serveur\n", nOctetsEnvoyes);
printf("texte envoye : %s", buffer);
}
else
printf("Erreur : donnees non envoyees au serveur");
// on reçoit les données envoyées par le serveur
nOctetsRecus = recv(sock, buffer, TAILLE_MAX, 0);
if(nOctetsRecus != SOCKET_ERROR)
{
printf("%d octets ont ete recus\n", nOctetsRecus);
printf("texte recu : %s", buffer);
}
else
printf("Les donnees n'ont pas ete recues");
// on ferme la connexion
closesocket(sock);
#if defined (WIN32)
WSACleanup(); // libère les ressources allouées par la fonction WSAStartup()
#endif
getchar();
return EXIT_SUCCESS;
}
你知道这个问题吗?
谢谢。
就是这个问题,
sprintf(buffer, "NICK hoeplem\r\n");
tailleBuffer = strlen(buffer)+1;
因为strlen(buffer) + 1
少了一个字节(不应将null
终止符'[=14=]'
发送到服务器并且strlen()
returns 字符串的 length 不包括 null
终止符。) 字符串的实际长度。如果服务器读取该字节,它可能期望 '\r\n'
刷新缓冲区并处理命令,因此它在最后一个“命令”之后永远等待。
应该是
tailleBuffer = sprintf(buffer, "NICK hoeplem\r\n");
这样就完美了。
您可能还想检查 POSIX's dprintf()
and/or 滚动自己的 dprintf()
以避免每次都 sprintf()
ing。
此外,最好将每个命令作为一个带有参数的函数,并为每个可能的命令简单地调用 command_X(sock, PARAMETERS ...)
,这样您的代码会更健壮。