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