来自 C 中 sendto() 套接字程序的无效参数
Invalid Argument from sendto() Socket Program in C
我正在尝试制作一个简单的客户端-服务器 API 用于我的两台机器。我制作了这个简单的程序,它使用我制作的功能来测试它。出于某种原因,我的客户端可以很好地发送消息,但我的服务器不能(但是,它从客户端接收消息)。
服务器端输出:
host name: my_host
Our port number is: 34440
Client msg: Client msg
Send failed: Invalid argument
Message from Server sent to Client
客户端输出:
Connection established with server...
Message from Client sent to Server
服务器端:
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"
int main() {
server_init();
char *msg = "Server msg";
char buffer[100];
int n = read_from_client((char *)buffer);
buffer[n] = '[=12=]';
printf("Client msg: %s\n", buffer);
write_to_client((char *)msg);
printf("Message from Server sent to Client \n");
return 0;
}
客户端:
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"
int main() {
client_init();
char *msg = "Client msg";
char buffer[100];
write_to_server((char*)msg);
printf("Message from Client sent to Server \n");
int n = read_from_server((char *)buffer);
buffer[n] = '[=13=]';
printf("Server msg: %s\n", buffer);
close_socket();
return 0;
}
my_socket.c:
#include "my_socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
int sockfd1;
int sockfd2;
int MAX_BUFF = 1024;
struct sockaddr_in server;
struct sockaddr_in client;
struct hostent *host;
ssize_t write_to_server(const void *buffer){
int bytes_sent, server_size = sizeof(server), buf_len = strlen(buffer);
if ((bytes_sent = sendto(sockfd2, buffer, buf_len, 0,
(const struct sockaddr *)&server, server_size)) < 0){
perror("Send failed");
}
return bytes_sent;
}
ssize_t write_to_client(const void *buffer){
int bytes_sent, client_size = sizeof(client), buf_len = strlen(buffer);
if ((bytes_sent = sendto(sockfd1, buffer, buf_len, 0,
(const struct sockaddr *)&client, client_size)) < 0){
perror("Send failed");
}
return bytes_sent;
}
int read_from_server(void *buffer){
int bytes_rcv, len;
if ((bytes_rcv = recvfrom(sockfd2, buffer, MAX_BUFF, MSG_WAITALL,
(struct sockaddr *)&server, &len)) < 0){
perror("Read failed");
}
return bytes_rcv;
}
int read_from_client(void *buffer){
int bytes_rcv, len;
if ((bytes_rcv = recvfrom(sockfd1, buffer, MAX_BUFF, MSG_WAITALL,
(struct sockaddr *)&client, &len)) < 0){
perror("Read failed");
}
return bytes_rcv;
}
void close_socket() {
close(sockfd1);
close(sockfd2);
}
void server_init(){
if ( (sockfd1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
}
char name[1024];
name[1023] = '[=14=]';
gethostname(name, 1023);
printf("host name: %s \n", name);
host = gethostbyname("my_host");
if(host == NULL){
perror("Host is null");
exit(0);
}
bzero((char *)&server, sizeof(server));
bzero((char *)&client, sizeof(client));
server.sin_family = AF_INET;
bcopy((char *)host->h_addr,
(char *)&server.sin_addr.s_addr, host->h_length);
//server.sin_port = 0;
server.sin_port = htons(34440);
if ( (bind(sockfd1, (struct sockaddr *)&server, sizeof(server) ) ) < 0 ){
perror("bind failed");
}
socklen_t len = sizeof(server);
if (getsockname(sockfd1, (struct sockaddr *)&server, &len) == -1){
perror("getsockname");
}else{
printf("Our port number is: %d\n", ntohs(server.sin_port));
}
}
void client_init(){
if ( (sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
}
host = gethostbyname("my_host");
if(host == NULL){
perror("Host is null");
exit(0);
}
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
bcopy((char *)host->h_addr,
(char *)&server.sin_addr.s_addr, host->h_length);
//server.sin_port = 0;
server.sin_port = htons(34440);
if(connect(sockfd2, (struct sockaddr *)&server, sizeof(server)) == 0){
printf("Connection established with server...\n");
}
}
my_socket.h:
#ifndef MY_SOCKET
#define MY_SOCKET
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
extern int sockfd1;
extern int sockfd2;
extern int MAX_BUFF;
extern struct sockaddr_in server;
extern struct sockaddr_in client;
extern struct hostent *host;
// Send a message over the socket
ssize_t write_to_server(const void *buffer);
ssize_t write_to_client(const void *buffer);
// Blocks until told it's ready; receives bytes from socket
int read_from_server(void *buffer);
int read_from_client(void *buffer);
// Close the socket
void close_socket();
void server_init();
void client_init();
#endif
欢迎任何建议或批评。提前致谢。
至少有一个问题是您没有在 read_from_client
中初始化 len
变量。 recvfrom
的手册页部分(强调)说:
... addrlen
is a value-result argument. Before the call, it should be initialized to the size of the buffer associated with src_addr
. Upon return, addrlen
is updated to contain the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case, addrlen
will return a value greater than was supplied to the call.
这意味着,作为一个未初始化的堆栈变量,len
具有不确定的值。可能为零,但至少小于 sizeof(struct sockaddr_in)
。结果,client
没有被 recvfrom
.
正确填写
就在 recvfrom
之前,您应该用以下方式初始化它:
len = sizeof(client);
在客户端,write_to_server
和 read_from_server
不需要使用 recvfrom
和 sendto
,因为您已经在套接字上完成了 connect
。他们可以简单地使用 recv
和 send
,因为远程套接字端点已经由 connect
建立。我相信对于已连接的套接字,地址只是被忽略了,但我现在找不到记录的位置。
(无论如何,如果您 做 继续在客户端使用 recvfrom
,您应该在那里进行相同的 len
初始化。)
我正在尝试制作一个简单的客户端-服务器 API 用于我的两台机器。我制作了这个简单的程序,它使用我制作的功能来测试它。出于某种原因,我的客户端可以很好地发送消息,但我的服务器不能(但是,它从客户端接收消息)。
服务器端输出:
host name: my_host
Our port number is: 34440
Client msg: Client msg
Send failed: Invalid argument
Message from Server sent to Client
客户端输出:
Connection established with server...
Message from Client sent to Server
服务器端:
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"
int main() {
server_init();
char *msg = "Server msg";
char buffer[100];
int n = read_from_client((char *)buffer);
buffer[n] = '[=12=]';
printf("Client msg: %s\n", buffer);
write_to_client((char *)msg);
printf("Message from Server sent to Client \n");
return 0;
}
客户端:
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"
int main() {
client_init();
char *msg = "Client msg";
char buffer[100];
write_to_server((char*)msg);
printf("Message from Client sent to Server \n");
int n = read_from_server((char *)buffer);
buffer[n] = '[=13=]';
printf("Server msg: %s\n", buffer);
close_socket();
return 0;
}
my_socket.c:
#include "my_socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
int sockfd1;
int sockfd2;
int MAX_BUFF = 1024;
struct sockaddr_in server;
struct sockaddr_in client;
struct hostent *host;
ssize_t write_to_server(const void *buffer){
int bytes_sent, server_size = sizeof(server), buf_len = strlen(buffer);
if ((bytes_sent = sendto(sockfd2, buffer, buf_len, 0,
(const struct sockaddr *)&server, server_size)) < 0){
perror("Send failed");
}
return bytes_sent;
}
ssize_t write_to_client(const void *buffer){
int bytes_sent, client_size = sizeof(client), buf_len = strlen(buffer);
if ((bytes_sent = sendto(sockfd1, buffer, buf_len, 0,
(const struct sockaddr *)&client, client_size)) < 0){
perror("Send failed");
}
return bytes_sent;
}
int read_from_server(void *buffer){
int bytes_rcv, len;
if ((bytes_rcv = recvfrom(sockfd2, buffer, MAX_BUFF, MSG_WAITALL,
(struct sockaddr *)&server, &len)) < 0){
perror("Read failed");
}
return bytes_rcv;
}
int read_from_client(void *buffer){
int bytes_rcv, len;
if ((bytes_rcv = recvfrom(sockfd1, buffer, MAX_BUFF, MSG_WAITALL,
(struct sockaddr *)&client, &len)) < 0){
perror("Read failed");
}
return bytes_rcv;
}
void close_socket() {
close(sockfd1);
close(sockfd2);
}
void server_init(){
if ( (sockfd1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
}
char name[1024];
name[1023] = '[=14=]';
gethostname(name, 1023);
printf("host name: %s \n", name);
host = gethostbyname("my_host");
if(host == NULL){
perror("Host is null");
exit(0);
}
bzero((char *)&server, sizeof(server));
bzero((char *)&client, sizeof(client));
server.sin_family = AF_INET;
bcopy((char *)host->h_addr,
(char *)&server.sin_addr.s_addr, host->h_length);
//server.sin_port = 0;
server.sin_port = htons(34440);
if ( (bind(sockfd1, (struct sockaddr *)&server, sizeof(server) ) ) < 0 ){
perror("bind failed");
}
socklen_t len = sizeof(server);
if (getsockname(sockfd1, (struct sockaddr *)&server, &len) == -1){
perror("getsockname");
}else{
printf("Our port number is: %d\n", ntohs(server.sin_port));
}
}
void client_init(){
if ( (sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
}
host = gethostbyname("my_host");
if(host == NULL){
perror("Host is null");
exit(0);
}
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
bcopy((char *)host->h_addr,
(char *)&server.sin_addr.s_addr, host->h_length);
//server.sin_port = 0;
server.sin_port = htons(34440);
if(connect(sockfd2, (struct sockaddr *)&server, sizeof(server)) == 0){
printf("Connection established with server...\n");
}
}
my_socket.h:
#ifndef MY_SOCKET
#define MY_SOCKET
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
extern int sockfd1;
extern int sockfd2;
extern int MAX_BUFF;
extern struct sockaddr_in server;
extern struct sockaddr_in client;
extern struct hostent *host;
// Send a message over the socket
ssize_t write_to_server(const void *buffer);
ssize_t write_to_client(const void *buffer);
// Blocks until told it's ready; receives bytes from socket
int read_from_server(void *buffer);
int read_from_client(void *buffer);
// Close the socket
void close_socket();
void server_init();
void client_init();
#endif
欢迎任何建议或批评。提前致谢。
至少有一个问题是您没有在 read_from_client
中初始化 len
变量。 recvfrom
的手册页部分(强调)说:
...
addrlen
is a value-result argument. Before the call, it should be initialized to the size of the buffer associated withsrc_addr
. Upon return,addrlen
is updated to contain the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case,addrlen
will return a value greater than was supplied to the call.
这意味着,作为一个未初始化的堆栈变量,len
具有不确定的值。可能为零,但至少小于 sizeof(struct sockaddr_in)
。结果,client
没有被 recvfrom
.
就在 recvfrom
之前,您应该用以下方式初始化它:
len = sizeof(client);
在客户端,write_to_server
和 read_from_server
不需要使用 recvfrom
和 sendto
,因为您已经在套接字上完成了 connect
。他们可以简单地使用 recv
和 send
,因为远程套接字端点已经由 connect
建立。我相信对于已连接的套接字,地址只是被忽略了,但我现在找不到记录的位置。
(无论如何,如果您 做 继续在客户端使用 recvfrom
,您应该在那里进行相同的 len
初始化。)