gpt4 book ai didi

C 套接字编程 - 从服务器写入(而不是客户端)写入服务器

转载 作者:可可西里 更新时间:2023-11-01 02:56:37 27 4
gpt4 key购买 nike

我正在开发一个 TCP 客户端服务器程序,它应该支持使用线程的多个客户端。

套接字创建、连接、绑定(bind)和接受按预期工作,因为我在运行代码时没有收到任何错误。
但是,每当我尝试从服务器读取()时,代码都会进入无限循环,并且没有任何 react 。

我先尝试从服务器写入,然后将写入结果写入服务器的终端。

客户端代码:

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

#define FILE_ADDR "/dev/urandom"

int main(int argc, char *argv[]) {

//Get command line arguments
unsigned int port = atoi(argv[2]);
int length = atoi(argv[3]); //Number of bytes to read
char* buffer = malloc(length * sizeof(char)); //Buffer to hold data read from file
char* recvBuf = malloc(10 * sizeof(char)); // Buffer to hold response from server

struct addrinfo hints, *servinfo, *p;
struct sockaddr_in serv_addr;
int sockfd = -1;
//int rv;
//char ip[100];

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
if (rv != 0) {
perror("getaddrinfo error\n");
exit(1);
}
for (p = servinfo; p != NULL; p = p->ai_next) {
//Initialize socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd < 0)
continue;
//Initialize connection
rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
if (rv == 0)
break;
close(sockfd);
sockfd = -1;
}
// inet_aton(ip, &h.sin_addr);
freeaddrinfo(servinfo);

//Open file for reading
FILE *fp;
fp = fopen(FILE_ADDR, "r");
if (fp == NULL) {
perror("Error in file open\n");
}
printf("file opened\n");
size_t numOfbytesRead = fread(buffer, sizeof(char), length, fp);
if (numOfbytesRead != length) {
perror("Error reading from file\n");
}
printf("Buffer is %s\n", buffer);

char* ptr;
unsigned int N = strtoul(argv[3],&ptr,10);
int convertedNum = htonl(N);

if (write(sockfd, &convertedNum, sizeof(unsigned int)) < 0) { //Send number of bytes
perror("error writing to socket");
}
if (write(sockfd, buffer, sizeof(buffer) < 0)) {//Send bytes read from file
perror("error writing to socket");

}

printf("send is done \n");

int bytes_read = read(sockfd, recvBuf, sizeof(recvBuf)); //Recieve response from server
if (bytes_read <= 0) {
perror("Error in recieving result from server\n");
}

unsigned int C = 0;
sprintf(recvBuf[0], "%d", C);

fclose(fp);
printf("# of printable characters: %u\n", C);
exit(0);
free(buffer);
free(recvBuf);

}

服务器代码:
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <pthread.h>
#include <signal.h>

static volatile int keepRunning = 1;
int pcc_total[159];

void intHandler(int dummy) {
keepRunning = 0;
}

void *compute(void *socket_desc) {
int count = 0;
int sock = *(int*) socket_desc;
printf("now will allocate N \n");
int n=0;
if (write(sock, "hi", 2) < 0) { //Send number of bytes
perror("error writing to socket\n");
}
if (read(sock, &n, sizeof(unsigned int)) < 0) {
perror("Error reading from socket\n");
exit(1);
}
int N = ntohl(n);
printf("len is %d\n", N);
char* data = calloc(N, sizeof(char));
int len = read(sock, data, N);
printf("data is %s\n", data);
if (len < 0) {
perror("Error reading from socket\n");
exit(1);
}
for (int i = 0; i < len; i++) {
int tmp = 0;
sprintf(data[i], "%d", tmp);
if (tmp >= 32 & tmp <= 126) {
count++;

__sync_fetch_and_add(&pcc_total[tmp], 1);
}
}
char scount[100];
atoi(count);
write(sock, count, strlen(scount));
free(data);
pthread_exit(NULL);
close(sock);
exit(0);
}

int main(int argc, char *argv[]) {

unsigned int port = atoi(argv[1]);
signal(SIGINT, intHandler);

int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
c = sizeof(struct sockaddr_in);

socket_desc = socket( AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
perror("Could not create socket");
exit(1);
}
printf("socket created\n");
memset(&server, 0, c);

server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);

if (0 != bind(socket_desc, (struct sockaddr*) &server, sizeof(server))) {
perror("\n Error : Bind Failed \n");
exit(1);
}
printf("bind created\n");
if (0 != listen(socket_desc, 10)) {
perror("\n Error : Listen Failed \n");
exit(1);
}
printf("listen created\n");
while (keepRunning) {
client_sock = accept(socket_desc, (struct sockaddr *) &client,
(socklen_t*) &c);
if (client_sock < 0) {
perror("\n Error : Accept Failed\n");
exit(1);
}
printf("accept created\n");
pthread_t tid;
new_sock = malloc(100*sizeof(int));
*new_sock = client_sock;
if ((pthread_create(&tid, NULL, compute, (void*) new_sock)) < 0) {
perror("could not create thread\n");
exit(1);
}
printf("thread created\n");
// close socket
close(client_sock);
free(new_sock);
pthread_join(tid, NULL);
}

exit(0);

}

我使用以下命令运行代码:

gcc -std=c99 -O3 -Wall -o pcc_server pcc_server.c -pthread

gcc -std=gnu99 -O3 -Wall -o pcc_client pcc_client.c

最佳答案

您的代码存在许多问题。
在客户端:

  • 打电话时fread() ,您需要使用 "rb"而不是 "r" .
  • 打电话时printf()要输出实际读取的文件数据,您不是空终止 buffer ,或传递其 lengthprintf() .你需要这样做。
  • 您正在分配 htonl() 的返回值到 int而不是 unsigned int .
  • 打电话时write()发送 buffer , 您正在使用 sizeof(buffer)什么时候应该使用 lengthN相反(以及为什么要使用两个单独的变量来保存相同的命令行参数值?)。 buffer是指向用 malloc() 分配的内存的指针, 所以 sizeof(buffer)sizeof(void*) 相同,这不是您想要的。此外,您甚至没有调用 write()正确,因为您的括号都是错误的(在发送 write() 时,它们在之前的 convertedNum 调用中是正确的)。
  • 同样,在调用 read() 时阅读 recvBuf , 您正在使用 sizeof(recvBuf)什么时候应该使用 10相反,西涅recvBuf也是指向 malloc 的指针ed 内存。
  • 您没有阅读 "hi"服务器在连接时发送给客户端的问候语,因此您将这些字节与下一条消息的以下大小值的字节混在一起,从而以损坏的 C 结束。值(value)。

  • 在服务器端:
  • 您的 compute线程例程发送 "hi"对客户端的问候,但它不使用任何类型的分隔符,例如在问候前加上其长度,或用换行符或空字符或其他唯一字符终止它,以将其与任何后续数据分开。您应该始终以某种方式分隔您的消息。
  • 您正在关闭 accept ed 套接字并释放 malloc编辑 new_sock一旦您创建了一个工作线程来处理该客户端。您正在从线程众所周知的背后撕掉内存。线程需要是关闭套接字并在使用完毕后释放内存的线程,而不是 accept环形。
    该线程确实尝试关闭套接字(但不释放内存),但在调用 pthread_exit() 之后首先,这是错误的。 pthread_exit()终止调用线程,所以它需要是线程调用的最后一件事(不要调用 exit() !)。事实上,甚至不要打电话pthread_exit()完全直接,只是return来自 compute() ,然后 pthreads 库将调用 pthread_exit()为你,随便传递 void*您选择的值 return .
  • 您的 accept循环不应调用 pthread_join()根本。它阻塞调用线程,直到指定的线程终止。这违背了使用线程处理客户端的全部目的,并阻止您的服务器一次接受 1 个以上的客户端。如果您打算使用 pthread_join()总而言之,它应该在 accept 之后循环已结束,因此您可以在退出应用程序之前等待任何可能仍在运行的工作线程。但这也意味着跟踪 pthread_t pthread_create() 的值返回,这是更多的工作。

  • 话虽如此,请尝试使用以下代码:
    客户端代码:
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <assert.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <dirent.h>

    #define FILE_ADDR "/dev/urandom"

    char* readMsg(int sockfd, size_t *msgSize)
    {
    *msgSize = 0;

    unsigned int length = 0;
    int bytes_read = read(sockfd, &length, sizeof(length)); //Receive number of bytes
    if (bytes_read <= 0) {
    perror("Error in receiving message from server\n");
    return NULL;
    }
    length = ntohl(length);

    char *buffer = malloc(length+1);
    if (!buffer) {
    perror("Error in allocating memory to receive message from server\n");
    return NULL;
    }

    char *pbuf = buffer;
    unsigned int buflen = length;
    while (buflen > 0) {
    bytes_read = read(sockfd, pbuf, buflen); // Receive bytes
    if (bytes_read <= 0) {
    perror("Error in receiving message from server\n");
    free(buffer);
    return NULL;
    }
    pbuf += bytes_read;
    buflen -= bytes_read;
    }

    *msgSize = length;
    return buffer;
    }

    int sendMsg(int sockfd, char *msg, size_t msgSize)
    {
    unsigned int convertedNum = htonl(msgSize);
    if (write(sockfd, &convertedNum, sizeof(convertedNum)) < 0) { //Send number of bytes
    perror("error writing to socket");
    return -1;
    }

    if (write(sockfd, msg, msgSize) < 0) { //Send bytes
    perror("error writing to socket");
    return -1;
    }

    return 0;
    }

    int main(int argc, char *argv[]) {

    char* ptr;

    //Get command line arguments
    unsigned int port = atoi(argv[2]);
    unsigned int length = strtoul(argv[3], &ptr, 10); //Number of bytes to read
    char* buffer = malloc(length); //Buffer to hold data read from file

    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_in serv_addr;
    int sockfd = -1;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
    if (rv != 0) {
    perror("getaddrinfo error\n");
    return 1;
    }
    for (p = servinfo; p != NULL; p = p->ai_next) {
    //Initialize socket
    sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if (sockfd < 0)
    continue;
    //Initialize connection
    rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
    if (rv == 0)
    break;
    close(sockfd);
    sockfd = -1;
    }
    freeaddrinfo(servinfo);

    if (sockfd == -1) {
    perror("socket create/connect error\n");
    return 1;
    }

    size_t msgSize;
    char *msg = readMsg(sockfd, &msgSize);
    if (!msg) {
    close(sockfd);
    return 1;
    }
    printf("%.*s\n", (int)msgSize, msg);
    free(msg);

    //Open file for reading
    FILE *fp = fopen(FILE_ADDR, "rb");
    if (fp == NULL) {
    perror("Error in file open\n");
    close(sockfd);
    return 1;
    }
    printf("file opened\n");

    if (fread(buffer, 1, length, fp) != length) {
    perror("Error reading from file\n");
    fclose(fp);
    close(sockfd);
    return 1;
    }
    fclose(fp);
    printf("Buffer is %.*s\n", (int)length, buffer);

    if (sendMsg(sockfd, buffer, length) != 0) {
    free(buffer);
    close(sockfd);
    return 1;
    }
    free(buffer);
    printf("send is done \n");

    msg = readMsg(sockfd, &msgSize); // response from server
    if (!msg) {
    close(sockfd);
    return 1;
    }
    printf("# of printable characters: %.*s\n", (int)msgSize, msg);
    free(msg);

    return 0;
    }
    服务器代码:
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <assert.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <dirent.h>
    #include <pthread.h>
    #include <signal.h>

    static volatile int keepRunning = 1;
    int pcc_total[159];

    void intHandler(int dummy) {
    keepRunning = 0;
    }

    char* readMsg(int sockfd, size_t *msgSize)
    {
    *msgSize = 0;

    unsigned int length = 0;
    int bytes_read = read(sockfd, &length, sizeof(length)); //Receive number of bytes
    if (bytes_read <= 0) {
    perror("Error in receiving message from server\n");
    return NULL;
    }
    length = ntohl(length);

    char *buffer = malloc(length+1);
    if (!buffer) {
    perror("Error in allocating memory to receive message from server\n");
    return NULL;
    }

    char *pbuf = buffer;
    unsigned int buflen = length;
    while (buflen > 0) {
    bytes_read = read(sockfd, pbuf, buflen); // Receive bytes
    if (bytes_read <= 0) {
    perror("Error in receiving message from server\n");
    free(buffer);
    return NULL;
    }
    pbuf += bytes_read;
    buflen -= bytes_read;
    }

    *msgSize = length;
    return buffer;
    }

    int sendMsg(int sockfd, char *msg, size_t msgSize)
    {
    unsigned int convertedNum = htonl(msgSize);
    if (write(sockfd, &convertedNum, sizeof(convertedNum)) < 0) { //Send number of bytes
    perror("error writing to socket");
    return -1;
    }

    if (write(sockfd, msg, msgSize) < 0) { //Send bytes
    perror("error writing to socket");
    return -1;
    }

    return 0;
    }

    void *compute(void *socket_desc) {
    int sock = * (int*) socket_desc;
    free(socket_desc);

    if (sendMsg(sock, "hi", 2) != 0) {
    perror("error writing to socket\n");
    close(sock);
    return NULL;
    }

    size_t length = 0;
    char *data = readMsg(sock, &length);
    if (!msg) {
    close(sock);
    return NULL;
    }
    printf("len is %d\n", (int)length);
    printf("data is %.*s\n", (int)length, data);

    int count = 0;
    for (size_t i = 0; i < length; i++) {
    // ...
    }
    free(data);

    char scount[20];
    sprintf(scount, "%d", count);
    sendMsg(sock, scount, strlen(scount));

    close(sock);
    return NULL;
    }

    int main(int argc, char *argv[]) {

    unsigned int port = atoi(argv[1]);
    signal(SIGINT, intHandler);

    int socket_desc, client_sock, c, *new_sock;
    struct sockaddr_in server, client;

    socket_desc = socket( AF_INET, SOCK_STREAM, 0);
    if (socket_desc == -1) {
    perror("Could not create server socket");
    return 1;
    }
    printf("server socket created\n");

    memset(&server, 0, c);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(port);

    if (bind(socket_desc, (struct sockaddr*) &server, sizeof(server)) < 0) {
    perror("\n Error : Bind Failed \n");
    close(socket_desc);
    return 1;
    }
    printf("bind created\n");

    if (listen(socket_desc, 10) < 0) {
    perror("\n Error : Listen Failed \n");
    close(socket_desc);
    return 1;
    }
    printf("listening\n");

    while (keepRunning) {
    c = sizeof(client);
    client_sock = accept(socket_desc, (struct sockaddr *) &client,
    (socklen_t*) &c);
    if (client_sock < 0) {
    perror("\n Error : Accept Failed\n");
    continue;
    }
    printf("client accepted\n");

    new_sock = malloc(sizeof(int));
    if (!new_sock) {
    perror("\n Error : Malloc Failed\n");
    close(client_sock);
    continue;
    }
    *new_sock = client_sock;

    pthread_t tid;
    if (pthread_create(&tid, NULL, &compute, new_sock) != 0) {
    perror("\n Error : Thread Create Failed\n");
    free(new_sock);
    close(client_sock);
    continue;
    }
    printf("thread created\n");
    }

    close(socket_desc);
    return 0;
    }

    关于C 套接字编程 - 从服务器写入(而不是客户端)写入服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48389076/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com