0

我正在尝试实现一个 tcp 客户端和 tcp 服务器。我能够建立连接,但是当我从客户端发送消息时,服务器没有收到它,是的,我确实看过以前的帖子,并且有很多类似的问题。我确实关注了他们,但我仍然遇到同样的错误。我得到的错误来自服务器端:

recv: Socket operation on non-socket

这是我的代码。如果您能告诉我我做错了什么,我将不胜感激。我认为我的服务器实现存在问题。

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3490
#define BACKLOG 10

int main()
{
    struct sockaddr_in server;
    struct sockaddr_in dest;
    int status,socket_fd, client_fd,num;
    socklen_t size;

    char buffer[10240];
    memset(buffer,0,sizeof(buffer));
    int yes = 1;

    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
        fprintf(stderr, "Socket failure!!\n");
        exit(1);
    }

    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    memset(&server, 0, sizeof(server));
    memset(&dest,0,sizeof(dest));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = INADDR_ANY; 
    if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1)    { //sizeof(struct sockaddr) 
        fprintf(stderr, "Binding Failure\n");
        exit(1);
    }

    if ((listen(socket_fd, BACKLOG))== -1){
        fprintf(stderr, "Listening Failure\n");
        exit(1);
    }

    while(1) {
        size = sizeof(struct sockaddr_in);  

        if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {
            //fprintf(stderr,"Accept Failure\n");
            perror("accept");
            exit(1);
        }

        printf("Server got connection from client %s\n", inet_ntoa(dest.sin_addr));
        //buffer = "Hello World!! I am networking!!\n";

        if ((num = recv(client_fd, buffer, 10239,0))== -1) {
            //fprintf(stderr,"Error in receiving message!!\n");
            perror("recv");
            exit(1);
        }   

        // num = recv(client_fd, buffer, sizeof(buffer),0);
        buffer[num] = '\0';
        printf("Message received: %s\n", buffer); 
        close(client_fd);   
        return 0;
        //close(socket_fd); 
    }    
}

客户:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 3490

int main(int argc, char *argv[])
{
    struct sockaddr_in server_info;
    struct hostent *he;
    int socket_fd,num;
    char *buffer;

    if (argc != 2) {
        fprintf(stderr, "Usage: client hostname\n");
        exit(1);
    }

    if ((he = gethostbyname(argv[1]))==NULL) {
        fprintf(stderr, "Cannot get host name\n");
        exit(1);
    }

    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
        fprintf(stderr, "Socket Failure!!\n");
        exit(1);
    }

    memset(&server_info, 0, sizeof(server_info));
    server_info.sin_family = AF_INET;
    server_info.sin_port = htons(PORT);
    server_info.sin_addr = *((struct in_addr *)he->h_addr);
    if (connect(socket_fd, (struct sockaddr *)&server_info, sizeof(struct sockaddr))<0) {
        //fprintf(stderr, "Connection Failure\n");
        perror("connect");
        exit(1);
    }

    buffer = "Hello World!! I am networking!!\n";
    if ((send(socket_fd,buffer, sizeof(buffer),0))== -1) {
        fprintf(stderr, "Failure Sending Message\n");
        close(socket_fd);
        exit(1);
    }
    else {
        printf("Message being sent: %s\n",buffer);
    }

    close(socket_fd);   
}
4

2 回答 2

1

我在 gdb 下运行服务器,在调用 accept() 后发现 client_fd 为 0。这是一个无效的套接字 fd,所以我查看了那行代码,发现右括号是错误的:

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {

应该:

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {

否则,它首先进行比较,然后将比较分配给 client_fd,而您想要分配套接字,然后进行比较。

为了避免这种令人沮丧的错误,通常认为最好的做法是不要将赋值放在“if”语句中。我会建议:

client_fd = accept(...);
if (client_fd < 0) { ... }

此外,在客户端中,对 send() 的调用使用“sizeof(buffer)”。'buffer' 是一个 char*,指针的大小是 4(在 32 位系统上),所以只会发送 'Hell'。要发送完整的字符串,请使用“strlen(buffer)”代替要发送的金额。

于 2012-07-09T01:41:43.450 回答
0

你的第一个问题是括号放错了。

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {

实际上应该是

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {

正如您目前拥有的那样,client_fd将分配给与返回值之间的相等性测试的结果,accept()因此-1在成功的情况下将始终为零。

这就是为什么许多程序员避免在 if 语句中进行赋值的原因之一。如果这样写

client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size);
if (client_fd == -1) {

那么错误就不会发生。

于 2012-07-09T01:34:35.797 回答