我正在嘗試使用編寫客戶端/服務器應用程序RAW套接字。原始套接字:sendto()和recvfrom()不工作
有多種問題:
當客戶端將消息發送到使用SENDTO服務器()方法,誤差無效參數由SENDTO()返回方法。 爲什麼會出現此錯誤訊息?。相應的代碼在錯誤1部分標記。 sendto()的代碼在這篇文章中有評論。
由於我已經評論了發送消息部分,客戶端應等待消息; recvfrom()是阻止系統調用。相反,recvfrom()總是返回消息E。 此消息來自哪裏?。相應的代碼被標記爲錯誤2。
如果我在插座()到或IPPROTO_RAW改變協議(3日)的說法,我得到協議不受支持的錯誤。爲什麼會出現這些錯誤?
操作系統是Ubuntu的。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h> // For the socket() etc. functions.
#include <netinet/in.h> // For IPv4 data struct..
#include <string.h> // For memset.
#include <arpa/inet.h> // For inet_pton().
#define BUF_SIZE 30
void main()
{
int rst; // Return status of functions.
/**************** Create a socket. *******************************/
int sfd; // Socket file descriptor.
sfd = socket (AF_INET, SOCK_RAW, IPPROTO_UDP); /*
* AF_INET --> IPv4, SOCK_RAW for Raw socket,
* 0 --> for any protocol. */
if (sfd == -1)
{
perror ("Client: socket error");
exit (1);
}
/*********** Server's address ***********************************/
struct sockaddr_in srv_addr;
socklen_t addrlen = sizeof (struct sockaddr_in);
// Initializing the server's address to zero.
memset (&srv_addr, 0, addrlen);
srv_addr.sin_family = AF_INET; // Address is in IPv4 format.
// srv_addr.sin_port = htons (0); // Port number of the server.
rst = inet_pton (AF_INET, "127.0.0.1", &srv_addr.sin_addr); /* Note
* that third field should point to an in_addr (in6_addr). */
if (rst <= 0)
{
perror ("Client Presentation to network address conversion.\n");
exit (1);
}
/****************** ERROR 1 ************************************
******************* Sending message to the server. *************/
const int flags = 0;
const char *msg = "Hello";
/* rst = sendto (sfd, msg, strlen(msg)+1, flags,
(struct sockaddr *) &srv_addr,
sizeof (struct sockaddr_in));
if (rst < 0)
{
perror ("Client: Sendto function call failed");
exit (1);
}
else
printf ("Client: Sent data size = %d\n", rst);
*/
/******************* ERROR 2 ***********************************
******************* Receiving message from server. ************/
// Initializing the server's address to zero.
memset (&srv_addr, 0, addrlen);
char buf[BUF_SIZE] = {'\0'};
rst = recvfrom (sfd, buf, BUF_SIZE, flags,
(struct sockaddr *) &srv_addr,
&addrlen);
if (rst < 0)
{
perror ("Client: couldn't receive");
exit (1);
}
printf ("Message from server = |%s|\n", buf);
/* Address of the server. */
const char *buf2 = inet_ntop (AF_INET,
(struct sockaddr *) &srv_addr, buf, BUF_SIZE);
if (buf2 == NULL)
{
perror ("Client: Conversion of sender's address to presentation failed");
exit (1);
}
printf ("Servers address, = %s\n", buf2);
close (sfd);
}
您的「錯誤1」對我來說工作正常。如果您需要進一步的調試幫助,您可以使用strace工具運行程序併發布輸出。請記住,原始套接字接收您的機器接收到的每個IP數據包。也許你正在收到一個DNS或SSH數據包等等,你打印出來的'E'是IP頭的1.字節。 IPv4數據包中的1個字節是0x45,在ASCII中被解釋爲E。所以,請記住,由於您使用RAW套接字,您也正在接收IP標頭。如果您使用IPPROTO_RAW,則需要創建您發送的有效IP標頭。 – nos