[英]socket connect() returns errno EINVAL
我正在開發一個用於c socket編程的小型演示應用程序,我遇到了連接到本地計算機上托管的服務器應用程序的問題。 當我調用connect()時,我得到了errno 22,它是EINVAL,我無法知道哪個參數無效以及為什么它無效。
我不確定是什么導致了這個錯誤。 我已經檢查了手冊頁,查看了我所做的所有調用,並查看了大約六個教程,據我所知,我似乎沒有遺漏任何碎片。
(順便說一下我用gcc來編譯應用程序)
誰能幫我?
client.c
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#define ARGBUF_SIZE 256
#define MAX_BUF 1024
void
post_error(const char* inMsg)
{
fprintf(stderr, "%s\n", inMsg);
perror("errno is ");
fflush(stderr);
exit(-1);
}
int
open_tcp(void)
{
return socket(PF_INET, SOCK_STREAM, 0);
}
int
open_udp(void)
{
return socket(PF_INET, SOCK_DGRAM, 0);
}
int
open_connection(const char* connectionType, struct sockaddr_in* target)
{
int handle = -1;
if (strcmp(connectionType, "tcp") == 0)
handle = open_tcp();
else if (strcmp(connectionType, "udp") == 0)
handle = open_udp();
else
post_error("error: invalid arguments - connection type can only be either \"tcp\" or \"udp\"");
/* attempt connection */
int result = connect(handle, (struct sockaddr*)&target, sizeof(target));
/* inspect errno for more information on the error */
/*
* this switch is unneeded since perror dumps the string for errno
* but it is useful for debugging
*/
fprintf(stdout, "errno is ");
switch (errno)
{
case EACCES:
fprintf(stdout, "EACCESS");
break;
case EPERM:
fprintf(stdout, "EPERM");
break;
case EADDRINUSE:
fprintf(stdout, "EADDRINUSE");
break;
case EAFNOSUPPORT:
fprintf(stdout, "EAFNOSUPPORT");
break;
case EAGAIN:
fprintf(stdout, "EAGAIN");
break;
case EALREADY:
fprintf(stdout, "EALREADY");
break;
case EBADF:
fprintf(stdout, "EBADF");
break;
case ECONNREFUSED:
fprintf(stdout, "ECONNREFUSED");
break;
case EFAULT:
fprintf(stdout, "EFAULT");
break;
case EINPROGRESS:
fprintf(stdout, "EINPROGRESS");
break;
case EINTR:
fprintf(stdout, "EINTR");
break;
case EISCONN:
fprintf(stdout, "EISCONN");
break;
case ENETUNREACH:
fprintf(stdout, "ENETUNREACH");
break;
case ENOTSOCK:
fprintf(stdout, "ENOTSOCK");
break;
case ETIMEDOUT:
fprintf(stdout, "ETIMEDOUT");
break;
default:
fprintf(stdout, "unknown error(%d)", errno);
break;
}
fprintf(stdout, "\n");
fflush(stdout);
if (result < 0)
post_error("error: invalid arguments? - connection failed");
printf("connection made");
return handle;
}
int
main(int argc, char* argv[])
{
int handle;
struct sockaddr_in target;
if (argc != 4)
post_error("usage: socket_client [tcp | udp] [server ip] [port number]");
/* argv[0] is expected to be sockcn the name of this executable */
memset(&target, 0, sizeof(target));
target.sin_family = AF_INET;
in_addr_t addr;
int result = inet_aton(argv[2], &addr);
if (result == INADDR_NONE)
post_error("error: invalid arguments - failed to convert ip address from string format");
target.sin_addr.s_addr = addr;
target.sin_port = htons(atoi(argv[3]));
handle = open_connection(argv[1], &target);
char buffer[MAX_BUF];
while (1)
{
printf("> ");
/* wait for input from user in faux-prompt and send to connection */
fgets(buffer, MAX_BUF, stdin);
if (strcmp(buffer, "exit\n") == 0)
break;
unsigned int len = strlen(buffer);
if (send(handle, buffer, len, 0) != len)
post_error("error: bytes sent is not the same as the size of the message");
}
close(handle);
return 0;
}
server.c
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define MAX_BUF 256
void
post_error(const char* inMsg)
{
fprintf(stderr, "%s", inMsg);
perror("errno is ");
exit(-1);
}
void
handle_client(int client)
{
char buffer[MAX_BUF];
int received = -1;
/* receive message */
received = recv(client, buffer, MAX_BUF, 0);
if (received < 0)
post_error("error: connection - failed to receive initial bytes from client");
while (received > 0)
{
printf("%s", buffer);
received = recv(client, buffer, MAX_BUF, 0);
if (received < 0)
post_error("error: connection - failed to received pending bytes from client");
}
close(client);
}
int
open_tcp(void)
{
return socket(AF_INET, SOCK_STREAM, 0);
}
int
open_udp(void)
{
return socket(AF_INET, SOCK_DGRAM, 0);
}
int
main(int argc, char* argv[])
{
int serverHandle;
int clientHandle;
struct sockaddr_in server;
struct sockaddr_in client;
if (argc != 3)
post_error("usage: server [tcp or udp] [port number]");
int udp;
if (strcmp(argv[1], "tcp") == 0)
{
udp = 0;
serverHandle = open_tcp();
}
else if (strcmp(argv[1], "udp") == 0)
{
udp = 1;
serverHandle = open_udp();
}
else
{
post_error("error: invalid arguments - first argument must be either \"tcp\" or \"udp\"");
}
/* construct the server struct */
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // htonl(INADDR_ANY);
server.sin_port = htons(atoi(argv[2]));
/* bind is used for server compared to connect for clients */
if (bind(serverHandle, (struct sockaddr*)&server, sizeof(server)) < 0)
post_error("error: failed to bind to target port");
if (!udp)
{
/* listen to start receiving messages */
if (listen(serverHandle, 1) < 0)
post_error("error: failed to listen on bound port");
}
fprintf(stdout, "server initialized.\nwaiting for messages...\n");
fflush(stdout);
/* now just wait for messages to come in */
/* the if should really be outside the while to avoid checking 'udp' every iteration but this seems fairly clear of the intention */
while (1)
{
if (udp)
{
char buffer[MAX_BUF];
socklen_t len = sizeof(client);
ssize_t received = recvfrom(serverHandle, buffer, MAX_BUF, 0, (struct sockaddr*)&client, &len);
fprintf(stdout, "> %s", buffer);
fflush(stdout);
}
else
{
/* wait for connection */
socklen_t len = sizeof(client);
if (clientHandle = accept(serverHandle, (struct sockaddr*)&client, &len) < 0)
post_error("error: failed to accept client connection");
fprintf(stdout, "client connected: %s\n", inet_ntoa(client.sin_addr));
fflush(stdout);
handle_client(clientHandle);
}
}
}
服務器使用./server運行tcp 65000客戶端使用./client tcp 65000運行
錯誤在這一行:
int result = connect(handle, (struct sockaddr*)&target, sizeof(target));
target
已經是一個你正在獲取地址的指針類型。 嘗試
int result = connect(handle, (struct sockaddr*)target, sizeof(*target));
請注意細微的sizeof(*target)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.