我正在练习通过能够接受来自多个客户端的多个响应来导致服务器并发运行的不同形式。这是学校布置的作业。
我现在有问题与线程。线程工作,但得到
错误。"curl: (56) Recv failure: Connection reset by peer"
这是因为响应函数中的行,我的线程去。请放心,除了clients[n]之外的所有变量基本上都是常量。所以它不是传递正确的,或者我完全错过了线程应该如何完成的标记。
rcvd = recv(clients[n], mesg, 99999, 0);
这一行一直返回-1到rcvd我想要> 0
这是我的代码。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<signal.h>
#include<fcntl.h>
#include<pthread.h>
#include "functions.h"
#define CONNMAX 1000
#define BYTES 1024
char *ROOT;
int verbose;
int signalReceived = 1;
int listenfd, clients[CONNMAX], slot;
pthread_t thread;
void error(char *);
void *threadServer(void *arg)
{
printf("bong");
respond(slot, verbose, ROOT, clients);
exit(0);
}
void clean(int arg)
{
signalReceived = 0;
}
int main(int argc, char *argv[])
{
signal(SIGINT, clean);
signal(SIGHUP, clean);
struct sockaddr_in clientaddr;
socklen_t addrlen;
char c;
char PORT[6];
ROOT = getenv("PWD");
strcpy(PORT, "8888");
while ((c = getopt (argc, argv, "p:v")) != -1)
switch (c)
{
case'v':
verbose = 1;
break;
case'p':
strcpy(PORT, optarg);
break;
case'?':
fprintf(stderr, "Wrong arguments givenn");
exit(1);
default:
exit(1);
}
printf("Listening on port %s%s%s, root is %s%s%sn", " 33[92m", PORT, " 33[0m", " 33[92m", ROOT, " 33[0m");
int i = 0;
for (i = 0; i < CONNMAX; i++)
clients[i] = -1;
startServer(PORT, &listenfd);
while (signalReceived == 1)
{
addrlen = sizeof(clientaddr);
clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
if (clients[slot] < 0)
exit(0);
else
{
printf("bang");
pthread_create(&thread, NULL, threadServer, NULL);
}
while (clients[slot] != -1)
slot = (slot + 1) % CONNMAX;
}
return 0;
}
我正在学习,这不是我的原创作品,而是为了学习而编辑的作品。我使用了一个分叉的原始程序,现在正试图将其转换为线程程序。
slot
为全局变量。启动一个线程可能需要一段时间,并且线程共享相同的内存。它们不像fork进程那样有自己的快照。
启动线程后,主进程修改 slot
。
最佳情况:新线程启动并获得slot的新值,使connections[slot] == -1
。最坏的情况:线程在不同的CPU核心上运行,并获得slot
,而 main正在写入它,导致坏值。
你可以考虑将slot
作为参数传递给线程函数:
void *threadServer(void *arg)
{
int mySlot = (int)arg;
printf("bongn");
respond(mySlot, verbose, ROOT, clients);
clients[mySlot] = -1;
printf("bashn");
return NULL; // calling 'exit' terminates the whole process. duh.
}
// ...
pthread_create(&thread, NULL, threadServer, (void*)slot);
你在这里遇到的另一个问题是,你创建了所有这些线程,但你没有单独跟踪它们。您可能需要一个线程数组,或者您可能想要考虑一个简单的结构体:
typedef struct Clients {
int fd;
pthread_t thread;
} Clients;
Clients clients[MAXCONN];
//
while (signalReceived == 1)
{
addrlen = sizeof(clientaddr);
clients[slot].fd = accept(listenfd, (struct sockaddr *) &clientaddr, &addrlen);
if (clients[slot].fd < 0)
exit(0);
else
{
printf("bang");
pthread_create(&clients[slot].thread, NULL, threadServer, (void*)slot);
}
while (clients[slot] != -1)
slot = (slot + 1) % CONNMAX; // what if we can't find one?
}
您的threadServer
函数调用exit
,终止进程。
我不确定这是从哪里来的,因为它在调用fork
的服务器中也不合适。但这在多线程程序中绝对是致命的。