意外的多线程服务器反应-C

意外的多线程服务器反应-C,c,multithreading,sockets,C,Multithreading,Sockets,我正在使用多线程服务器/客户端。我遇到的问题是,服务器处理有时看起来有点不同。返回的消息总是正确的,但是服务器打印出来的消息有点奇怪。如果它是一个像“你好”这样的短词,那么一切都是有效的。如果是一个长单词或字符串中有空格,如“Binominalkoeffizient”,则输出的服务器端消息为: Binomina lkoeffiz ient fiz 知道我的错在哪里吗 PS:当我使用telnet时,服务器的反应是一样的 主服务器: #include <stdio.h> #includ

我正在使用多线程服务器/客户端。我遇到的问题是,服务器处理有时看起来有点不同。返回的消息总是正确的,但是服务器打印出来的消息有点奇怪。如果它是一个像“你好”这样的短词,那么一切都是有效的。如果是一个长单词或字符串中有空格,如“Binominalkoeffizient”,则输出的服务器端消息为:

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;

}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“server.h”
int main(int argc,const char*argv[]{
int袜子;
服务器中的结构sockaddr_;
sock=socket(AF\u INET,sock\u STREAM,0);
socketStatusCheck(sock);
放置(“[*]启动服务器…”);
放置(“[*]初始化服务器…”);
初始化服务器(&server,8888);
bindServerToAddress(sock,server);
放置(“[*]等待输入连接…”);
认沽权(“”);
听(sock,3);
连接开关(插座);
关闭(袜子);
返回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;

}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“server.h”
void socketStatusCheck(int sock){
如果(sock==-1){
perror(“创建套接字时出错:”);
出口(0);
}
}
void initializeServer(服务器中的结构sockaddr_,int端口){
服务器->sin_family=AF_INET;
服务器->sin\u addr.s\u addr=INADDR\u ANY;
服务器->单端口=htons(端口);
}
void bindServerToAddress(服务器中的int sock、struct sockaddr_){
if(绑定(sock,(struct sockaddr*)和服务器,sizeof(服务器))<0){
perror(“错误绑定端口:”);
}
}
无效连接开关(内部插座){
兰布夫内诺克;
客户端中的结构sockaddr_;
pthread_t pid=NULL;
lenbuf=sizeof(结构sockaddr_in);
而((nsock=accept(sock,(struct sockaddr*)和client,(socklen_t*)和lenbuf))){
puts(“客户端已连接!”);
if(pthread_create(&pid,NULL,connectionHandler,(void*)&nsock))
perror(“创建线程时出错:”);
}
如果(nsock<0){
perror(“接受输入客户时出错:”);
}
pthread_exit(pid);
}
void*connectionHandler(void*sockptr){
int sock=*(int*)sockptr;
长时间断开连接;
char*smessage,*recvmessage;
smessage=“你好!我是您刚刚连接的服务器!\n”;
写(sock、smessage、strlen(smessage));
recvmessage=malloc(5000*sizeof(char));//而((isConnected=recv(sock,recvmessage,sizeof(recvmessage),0))>0)
而((isConnected=recv(sock,recvmessage,sizeof(recvmessage),0))>0){
//写入(sock、recvmessage、sizeof(recvmessage));
发送(sock,recvmessage,sizeof(recvmessage),0);
put(recvmessage);
}
如果(未连接==0){
perror(“客户端断开连接:”);
fflush(stdout);
}
free(recvmessage);recvmessage=NULL;
返回0;
}

这实际上与多线程无关,而与
SOCK\u流的性质有关

顾名思义,流套接字是字节流;它们不保留消息边界,因此一次调用
send
所发送的内容将被一次调用
recv
所接收。一个
send
可以在多个
recv
调用中分解,或者多个
send
调用可以合并为一个
recv
,或者两者都合并。它们确实保证了顺序,因为字节的接收顺序与发送顺序相同


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

这实际上与多线程无关,而与
SOCK\u STREAM
套接字的性质有关

顾名思义,流套接字是字节流;它们不保留消息边界,因此一次调用
send
所发送的内容将被一次调用
recv
所接收。一个
send
可以在多个
recv
调用中分解,或者多个
send
调用可以合并为一个
recv
,或者两者都合并。它们确实保证了顺序,因为字节的接收顺序与发送顺序相同


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

这是正常行为。使用
send
时,您不知道将发送多少字节。可能所有的单词、字符都会被发送,但是有办法解决这个问题。一种方法是向发送的字符串写入一个简单的头,其中包含要发送的字符串的长度。所以你知道字符串什么时候结束。例如,您可以使用线程连续查找消息,并且由于标头包含您知道何时打印消息的字符串长度,\n因此,
send
的行为无法更改,因为它是执行此操作的内核。

这是正常行为。使用
send
时,您不知道将发送多少字节。可能所有的单词、字符都会被发送,但是有办法解决这个问题。一种方法是向发送的字符串写入一个简单的头,其中包含要发送的字符串的长度。所以你知道字符串什么时候结束。例如,您可以使用线程连续查找消息,因为标头包含您知道何时打印消息的字符串长度。\n不能更改
发送的行为,因为它是执行此操作的内核。

除了其他答案所说的外:

您的代码明确要求一次读取8个字节<代码>recvmessage