2017-02-15 26 views
0

我正在使用多线程服务器/客户端。我遇到的问题是服务器处理有时看起来有点不同。发回的消息总是正确的,但服务器打印的消息有点奇怪。如果它是一个像“你好”这样的简短字,那么一切正常。如果是长字或有空间,如“Binominalkoeffizient”失印serversided消息字符串是:意外的多线程服务器反应 - C

Binomina 
lkoeffiz 
ient 
fiz 

任何想法,我的错误是什么?

PS:当我使用telnet时,服务器反应是一样的!

服务器主营:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <pthread.h> 

#include "server.h" 

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

    int sock; 
    struct sockaddr_in server; 

    sock = socket(AF_INET, SOCK_STREAM, 0); 
    socketStatusCheck(sock); 

    puts("[*] Starting Server ..."); 
    puts("[*] Initialize Server ..."); 
    initializeServer(&server, 8888); 
    bindServerToAddress(sock, server); 

    puts("[*] Waiting for incomming connections ... "); 
    puts(""); 
    listen(sock, 3); 

    connectionSwitch(sock); 

    close(sock); 

    return 0; 

} 

服务器的文件

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <pthread.h> 

#include "server.h" 


void socketStatusCheck(int sock) { 
    if (sock == -1) { 
     perror("Error creating the socket: "); 
     exit(0); 
    } 
} 

void initializeServer(struct sockaddr_in *server, int port) { 
    server->sin_family = AF_INET; 
    server->sin_addr.s_addr = INADDR_ANY; 
    server->sin_port = htons(port); 
} 

void bindServerToAddress(int sock, struct sockaddr_in server) { 
    if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0) { 
     perror("Error binding port: "); 
    } 
} 

void connectionSwitch(int sock) { 

    int nsock, lenbuf; 
    struct sockaddr_in client; 
    pthread_t pid = NULL; 

    lenbuf = sizeof(struct sockaddr_in); 
    while ((nsock = accept(sock, (struct sockaddr*) &client, (socklen_t*) &lenbuf))) { 
     puts("Client connected!"); 
     if (pthread_create(&pid, NULL, connectionHandler, (void*) &nsock)) 
      perror("Error creating thread: "); 
    } 
    if (nsock < 0) { 
     perror("Error accepting incomming client: "); 
    } 

    pthread_exit(pid); 

} 

void *connectionHandler(void *sockptr) { 

    int sock = *(int*) sockptr; 
    long isConnected; 
    char *smessage, *recvmessage; 

    smessage = "Hello! I am the server you just connected! \n"; 
    write(sock, smessage, strlen(smessage)); 

    recvmessage = malloc(5000 * sizeof(char)); // while ((isConnected = recv(sock, recvmessage, sizeof(recvmessage), 0)) > 0) 
    while ((isConnected = recv(sock, recvmessage, sizeof(recvmessage), 0)) > 0) { 
     //write(sock, recvmessage, sizeof(recvmessage)); 
     send(sock, recvmessage, sizeof(recvmessage), 0); 
     puts(recvmessage); 
    } 

    if (isConnected == 0) { 
     perror("Client disconnected: "); 
     fflush(stdout); 
    } 

    free(recvmessage); recvmessage = NULL; 

    return 0; 

} 
+0

'free(recvmessage); recvmessage = NULL;'是毫无意义的,删除第二条语句。 –

+0

那是因为你一次只能读取8个字节('sizeof(recvmessage)'是8),并且你在读完每组8个字节后打印换行符。 – immibis

回答

3

这真的没有任何做多线程,什么都做的SOCK_STREAM插座性质。

顾名思义,流套接字是字节流;他们不保留消息边界,以便通过一次呼叫recv收到一个与send的呼叫一起发送的内容。单个send可能会被分成多个recv调用,或者多个send调用可能会合并成一个单独的recv或两者。它们确保顺序,因为字节将按照它们发送的相同顺序接收。

您需要实现自己的记录标记,可能需要插入\0字符来分隔单词,或者使用长度前缀。

+0

好吧!非常感谢你!我会尝试使用\ 0 – Josey

+0

@Josey考虑接受这个答案来创建这样的记录标记,如果它最有帮助的话。 –

+0

非常感谢! – Josey

0

这是正常行为。当您使用send时,您不知道将发送多少个字节。可能会发生所有的单词,字符都被发送。但是有办法解决这个问题。一种方法是给你发送的字符串写一个简单的头文件,其中包含你发送的字符串的长度。所以你知道字符串何时结束。例如,您可以使用线程持续查看消息,并且由于头部包含字符串的长度,因此您知道何时打印\ n。send的行为不能更改,因为它是内核,就是这样做的。

+0

也谢谢!真的有帮助! – Josey

0

除了什么其他的答案已经说:

你的代码,明确要求在每次读取8个字节。 recvmessage是一个指针,并且指针在系统上是8个字节,所以sizeof(recvmessage)是8.