-3

我正在编写要在服务器端执行的套接字编程代码。现在,客户端基本上以字符串(通过 TCP)的形式发送数据。我的服务器代码试图做的是读取字符串并仅将数字存储在数组中,以便可以对获得的这些数字执行其他功能。但我完全不知道如何实现这个功能。

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


int main()
{
    int sock, connected, bytes_recieved , true = 1;  
    int n[3],i,arr[3][5];
    char send_data [1024] , recv_data[1024];       

    struct sockaddr_in server_addr,client_addr;    
    int sin_size;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket");
        exit(1);
    }

    if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {
        perror("Setsockopt");
        exit(1);
    }

    server_addr.sin_family = AF_INET;         
    server_addr.sin_port = htons(5001);     
    server_addr.sin_addr.s_addr = INADDR_ANY; 
    bzero(&(server_addr.sin_zero),8); 

    if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
        perror("Unable to bind");
        exit(1);
    }

    if (listen(sock, 5) == -1) {
        perror("Listen");
        exit(1);
    }

    printf("\nTCPServer Waiting for client on port 5000");
    fflush(stdout);

    while(1) {  
        sin_size = sizeof(struct sockaddr_in);
        connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
        printf("\n I got a connection from (%s , %d)",
               inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
        while (1) {
            printf("\n SEND (q or Q to quit) : ");
            gets(send_data);

            if (strcmp(send_data , "q") == 0 || strcmp(send_data , "Q") == 0) {
                send(connected, send_data,strlen(send_data), 0); 
                close(connected);
                break;
            } 
            else {
                send(connected, send_data,strlen(send_data), 0);
            } 

            for(i=0;i<3;i++) {
                bytes_recieved= recv(connected,recv_data,1024,0);
                recv_data[bytes_recieved] = '\0';

                n[i]=atoi(recv_data);     
            }

            if (strcmp(recv_data , "q") == 0 || strcmp(recv_data , "Q") == 0) {
                close(connected);
                break;
            }
            else  {
                for(i=0;i<3;i++) {
                    printf("\n RECIEVED DATA = %d \n",n[i]);
                    fflush(stdout);
                }
            }
        } /* end inner while */

        close(sock);
        return 0;
    } /* end outer while */
} /* end main */
4

1 回答 1

1

您并没有真正说出问题所在,也没有显示您的客户端代码。但我怀疑这是您的服务器循环中的问题。

for(i=0;i<3;i++)
{
    bytes_recieved= recv(connected,recv_data,1024,0);
    recv_data[bytes_recieved] = '\0';
    n[i]=atoi(recv_data);     
}

首先,如果 recv() 返回 1024,您最终会在 recv_data[1024] 处写入一个 '\0'。此数组的有效索引范围是 0..1023。您可以通过在此函数顶部将 recv_data 声明为 1025 字节而不是 1024 来轻松解决此问题。

但真正的问题是,无论客户端实际发送的字节数如何,都不能期望 recv() 返回任何预期的长度。(或者其他人会告诉你:“TCP 是一种 STREAM 协议”)

这可能是您想要的 recv() 循环。

for (i = 0; i < 3; i++)
{
    j=0; // j is declared as 32-bit int above
    success = ReadIntegerFromSocketStream(connected, &j);
    if (success == 0)
    {
        close(connected);
        connected = -1;
        break;
    }
    n[i] = j;
}

int ReadIntegerFromSocketStream(int sock, int* result)
{
    int ret;
    int count= 0;

    char COMPILE_TIME_ASSERT[ (sizeof(int)==4) ? 1 : -1 ];

    unsigned char data[4];

    while (bytes_received < 4)
    {
        ret = recv(sock, data+count, 4-count, 0);
        if (ret <= 0)
        {
            /* socket got closed, abort */
            return 0;
        }
        count += ret;
    }

    memcpy(&result, data, 4);

    // not shown: calling result = ntohl(result);
    // I'll let you look this function up

    return 1;
}
于 2012-11-11T07:48:20.150 回答