我正在使用多线程服务器/客户端。我遇到的问题是服务器处理有时看起来有点不同。发回的消息总是正确的,但服务器打印出来的消息有点奇怪。如果它是一个简短的词,比如"你好"一切正常。如果它是一个长字或字符串中有空格,如" Binominalkoeffizient" out-printed serversided消息是:
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 :(得分:3)
这与多线程无关,而且与Ambiguous column name 'Id'.
套接字的性质有关。
如图所示,流套接字是一个字节流;它们不保留消息边界,以便通过一次调用SOCK_STREAM
接收一次调用send
时发送的内容。单个recv
可以在多个send
来电中分解,或者多个recv
来电可以合并为一个send
,或两者兼而有之。它们确实保证了顺序,因为字节将按照它们发送的相同顺序接收。
您需要实现自己的记录标记,可能是通过插入recv
个字符来分隔单词,或者使用长度前缀。
答案 1 :(得分:0)
这是正常行为。当您使用send
时,您不知道将发送多少字节。可能会发生所有单词,字符都被发送。但是有办法解决这个问题。一种方法是将一个简单的标题写入您发送的字符串,其中包含您要发送的字符串的长度。所以你知道字符串何时结束。例如,您可以使用线程持续查找消息,因为标题包含您知道何时打印\ n的字符串长度。send
的行为无法更改,因为它是内核,就是这样做。
答案 2 :(得分:0)
除了其他答案已经说明的内容之外:
您的代码特别要求一次读取8个字节。 recvmessage
是一个指针,系统上的指针是8个字节,因此sizeof(recvmessage)
为8。