使用数据报的并发服务器

iro*_*wer 3 c pthreads datagram unix-socket

客户端必须向服务器发送 2 个字符串,服务器必须向客户端发回一个字符串,并且并行处理客户端。这两个实体在 Unix 下使用数据报交换数据。我的问题是,当我使用线程时,我无法将数据发送回客户端,也无法读取数据。此外,即使我不使用线程,我也无法将消息正确发送回客户端。

\n\n

服务器是:

\n\n
#include <sys/socket.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n#include <signal.h>\n#include <unistd.h>\n#include <stdlib.h>\n\n\nint sd = 0;\nvoid* worker(void* argm) {\n    struct sockaddr_in* adress = (struct sockaddr_in*) argm;\n    char s[100],s2[100];\n    int adressLen;\n\n    recvfrom(sd, s, sizeof(s), 0, (struct sockaddr*) &adress, &adressLen);\n    perror("recv");\n
Run Code Online (Sandbox Code Playgroud)\n\n

Perror显示recv:非套接字上的套接字操作

\n\n
    printf("I received: %s\\n",s);\n\n    strcat(s2,"sample");\n    s2[strlen(s2)]=\'\\0\';\n    sendto(sd, &s2, sizeof(s2),  0, (struct sockaddr*) &adress,sizeof(adress));\n    perror("send");\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后perror()显示发送:非套接字上的套接字操作。\n这也会导致客户端无限等待来自服务器的字符串。

\n\n
int main(int argc, char* argv[]) {\n    int sd;\n    int servPort;\n\n    struct sockaddr_in servAddr;  \n\n    if (argc != 2){\n        printf("usage %s <port server>\\n", argv[0]);\n        return 1;\n    }\n\n    if (1 != sscanf(argv[1], "%d", &servPort) || 0 > servPort || 0xffff < servPort){\n        printf("%s invalid port\\n",argv[1]);\n        return 2;   \n    }\n        servPort = htons(servPort);\n\n    sd = socket(AF_INET, SOCK_DGRAM, 0);\n    perror("socket: ");\n\n\n    servAddr.sin_family = AF_INET;\n    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);\n    servAddr.sin_port = servPort;\n\n    bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));\n    perror("bind");\n\n\n    for(;;) {\n        char s[100];\n        struct sockaddr_in client;\n        client.sin_family=AF_INET;\n        int clientLen;\n\n\n\n        recvfrom(sd, s, sizeof(s), 0, (struct sockaddr*) &client, &clientLen);\n        perror("recv");\n        printf("I received: %s\\n",s);\n\n        pthread_t thread;\n        pthread_create(&thread, NULL, worker, (void*) &client);\n        pthread_join(thread, NULL);\n\n        }\n    close(sd);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

控制台打印的内容:

\n\n
bind: Success\nrecv: Success\nI received: da\n\nrecv: Socket operation on non-socket\nI received: `\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\nsend: Socket operation on non-socket\nrecv: Success\nI received: nu\n\nrecv: Socket operation on non-socket\nI received: `\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\nsend: Socket operation on non-socket\n
Run Code Online (Sandbox Code Playgroud)\n\n

客户是:

\n\n
  #include <arpa/inet.h>\n#include <errno.h>\n#include <netdb.h>\n#include <netinet/ip.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <time.h>\n#include <unistd.h>\n\n\nint main(int argc, char *argv[])\n{\n    int sd, r, lung, n;\n    struct sockaddr_in servAddr;\n    struct hostent *h;\n    int servPort;\n\n\n    if (argc != 3){\n        printf("usage %s <IP server> <port server>\\n", argv[0]);\n        return 1;\n    }\n\n    h = gethostbyname(argv[1]);\n    if(h==NULL) {\n        printf("%s: unknown host \'%s\'\\n",argv[0],argv[1]);\n        return 1;\n    }\n\n        if (1 != sscanf(argv[2], "%d", &servPort) || 0 > servPort || 0xffff < servPort){\n        printf("%s invalid port \\n",argv[2]);\n        return 2;   \n    }\n        servPort = htons(servPort);\n\n    servAddr.sin_family = h->h_addrtype;\n    memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);\n    servAddr.sin_port = servPort;\n\n    sd = socket(AF_INET,SOCK_DGRAM,0);\n    perror("socket ");\n\n\n    char s[100],s2[100],s3[100];\n    printf("enter text 1:\\n");\n    fgets(s, 101, stdin);\n    printf("enter text 2:\\n");\n    fgets(s2, 101, stdin);\n\n    s[strlen(s)] = \'\\0\';\n    s2[strlen(s2)]=\'\\0\';\n\n    sendto(sd, &s, sizeof(s), 0, (struct sockaddr*) &servAddr, sizeof(servAddr));\n    perror("send");\n\n    sendto(sd, &s2, sizeof(s2), 0, (struct sockaddr*) &servAddr, sizeof(servAddr));\n    perror("send");\n\n\n    n = recvfrom(sd, s3, sizeof(s3), 0, (struct sockaddr*) &servAddr, &lung);\n    perror("recv");\n\n\n    printf("I received : %s", s3);\n\n    close(sd);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Jon*_*ler 5

服务器中的主要问题是您int sd = 0;在文件顶部有一个由 所使用的全局变量,并且在\xe2\x80\x94 中也worker()有一个局部变量。in中的变量被初始化到socket;全局变量仍然指向标准输入 (0),因此您尝试在非套接字上进行套接字操作。main()int sd;main()

\n\n

工作代码 \xe2\x80\x94server.c

\n\n

使用 mystderr.c和stderr.hcode 报告错误。如果您需要代码,请通过电子邮件与我联系(请参阅我的个人资料)。我没有做过任何标头最小化。

\n\n
#include <sys/socket.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n#include <signal.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include "stderr.h"\n\nint sd = 0;\n\nstatic void *worker(void)\n{\n    struct sockaddr_in address;\n    socklen_t          addressLen = sizeof(address);\n    char msg[100];\n\n    printf("%s(): sd = %d\\n", __func__, sd);\n    ssize_t n = recvfrom(sd, msg, sizeof(msg), 0, (struct sockaddr*) &address, &addressLen);\n    if (n < 0)\n        err_syserr("recvfrom() (worker) failed: ");\n    else if (n == 0)\n        err_report(ERR_EXIT, 0, "orderly shutdown by peer\\n");\n\n    err_remark("received: (%d bytes) %.*s\\n", (int)n, (int)n, msg);\n    msg[n] = \'\\0\';\n\n    strcat(msg, ": example");\n    size_t len = strlen(msg);\n    if ((n = sendto(sd, &msg, len, 0, (struct sockaddr*) &address, addressLen)) < 0)\n        err_syserr("error on sendto(): ");\n    err_remark("sent %d bytes\\n", (int)n);\n    return(0);\n}\n\nint main(int argc, char* argv[])\n{\n    int servPort;\n    struct sockaddr_in servAddr;\n\n    err_setarg0(argv[0]);\n    err_setlogopts(ERR_PID|ERR_STAMP);  /* tag output with PID and time */\n\n    if (argc != 2)\n        err_usage("portnum");\n\n    if (1 != sscanf(argv[1], "%i", &servPort) || 0 > servPort || 0xffff < servPort)\n        err_error("invalid port %s\\n", argv[1]);\n    servPort = htons(servPort);\n\n    if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)\n        err_syserr("error on socket(): ");\n\n    servAddr.sin_family = AF_INET;\n    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);\n    servAddr.sin_port = servPort;\n\n    if (bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)\n        err_syserr("error on bind(): ");\n\n    for (;;)\n    {\n        char msg[100];\n        struct sockaddr_in client;\n        client.sin_family = AF_INET;\n        socklen_t clientLen = sizeof(client);\n\n        ssize_t n = recvfrom(sd, msg, sizeof(msg), 0, (struct sockaddr*) &client, &clientLen);\n        if (n < 0)\n            err_syserr("error on recvfrom(): ");\n        if (n == 0)\n            err_report(ERR_EXIT, 0, "orderly shutdown by peer\\n");\n        err_remark("received: (%d bytes) %.*s\\n", (int)n, (int)n, msg);\n\n        worker();\n    }\n\n    close(sd);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

工作代码 \xe2\x80\x94client.c

\n\n
#include <arpa/inet.h>\n#include <errno.h>\n#include <netdb.h>\n#include <netinet/ip.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <time.h>\n#include <unistd.h>\n#include "stderr.h"\n\nint main(int argc, char *argv[])\n{\n    int sd;\n    ssize_t n;\n    struct sockaddr_in servAddr;\n    struct hostent *h;\n    int servPort;\n    socklen_t addrlen;\n\n    err_setarg0(argv[0]);\n\n    if (argc != 3)\n        err_usage("hostname portnum");\n\n    h = gethostbyname(argv[1]);\n    if (h==NULL)\n        err_syserr("unknown host %s: ", argv[1]);\n\n    if (1 != sscanf(argv[2], "%d", &servPort) || 0 > servPort || 0xffff < servPort)\n        err_error("invalid port %s\\n", argv[2]);\n    servPort = htons(servPort);\n\n    servAddr.sin_family = h->h_addrtype;\n    memcpy(&servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);\n    servAddr.sin_port = servPort;\n\n    if ((sd = socket(AF_INET,SOCK_DGRAM,0)) < 0)\n        err_syserr("error on socket(): ");\n\n    char s1[100],s2[100],s3[100];\n    printf("enter text 1:\\n");\n    fgets(s1, sizeof(s1), stdin);\n    printf("enter text 2:\\n");\n    fgets(s2, sizeof(s2), stdin);\n\n    size_t s1_len = strlen(s1) - 1;\n    size_t s2_len = strlen(s2) - 1;\n    s1[s1_len] = \'\\0\';  /* zap newline */\n    s2[s2_len] = \'\\0\';  /* zap newline */\n\n    if (sendto(sd, &s1, s1_len, 0, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)\n        err_syserr("sendto() (s1) failed: ");\n\n    if (sendto(sd, &s2, s2_len, 0, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)\n        err_syserr("sendto() (s2) failed: ");\n\n    if ((n = recvfrom(sd, s3, sizeof(s3), 0, (struct sockaddr*) &servAddr, &addrlen)) < 0)\n        err_syserr("recvfrom() (s3) failed: ");\n\n    printf("Client received: (%d bytes) %.*s\\n", (int)n, (int)n, s3);\n\n    close(sd);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

样本输出

\n\n

从构建程序、运行服务器以及两次运行客户端程序进行跟踪。该-I目录保存stderr.h并且-L目录保存libjl.a其中包括从 构建的目标文件stderr.c。

\n\n
$ make server client\ngcc -O3 -g -I/Users/jleffler/inc -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition server.c -o server -L/Users/jleffler/lib/64 -ljl\ngcc -O3 -g -I/Users/jleffler/inc -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition client.c -o client -L/Users/jleffler/lib/64 -ljl\n$ ./server 12345 &\n$ ./client localhost 12345\nenter text 1:\nGoliath Beetle\nenter text 2:\nGolgafrincham Excesses\nserver: 2013-03-25 20:51:23 - pid=10895: received: (14 bytes) Goliath Beetle\nworker(): sd = 3\nserver: 2013-03-25 20:51:23 - pid=10895: received: (22 bytes) Golgafrincham Excesses\nserver: 2013-03-25 20:51:23 - pid=10895: sent 31 bytes\nClient received: (31 bytes) Golgafrincham Excesses: example\n$ ./client localhost 12345\nenter text 1:\nSmall talk - what people say to each other\nenter text 2:\nSmalltalk - an archetypal object-oriented programming language\nserver: 2013-03-25 20:52:14 - pid=10895: received: (42 bytes) Small talk - what people say to each other\nworker(): sd = 3\nserver: 2013-03-25 20:52:14 - pid=10895: received: (62 bytes) Smalltalk - an archetypal object-oriented programming language\nserver: 2013-03-25 20:52:14 - pid=10895: sent 71 bytes\nClient received: (71 bytes) Smalltalk - an archetypal object-oriented programming language: example\n$\n
Run Code Online (Sandbox Code Playgroud)\n