C 带pthreads的套接字问题
我正在创建一个服务器/客户端echo程序。客户端读取字符串,发送到服务器,服务器将字符串发送回客户端 数据结构:C 带pthreads的套接字问题,c,sockets,pthreads,C,Sockets,Pthreads,我正在创建一个服务器/客户端echo程序。客户端读取字符串,发送到服务器,服务器将字符串发送回客户端 数据结构: typedef struct writeStruct { FILE *wsock; int sockfd; } writeStruct; typedef struct readStruct { FILE *rsock; int sockfd; } readStruct; 主要功能的一部分: main() { writeStruct *wr
typedef struct writeStruct
{
FILE *wsock;
int sockfd;
} writeStruct;
typedef struct readStruct
{
FILE *rsock;
int sockfd;
} readStruct;
主要功能的一部分:
main()
{
writeStruct *writeData;
readStruct *readData;
writeData = malloc(sizeof(writeData));
readData = malloc(sizeof(readData));
pthread_t write;
pthread_t read;
FILE *rsock, *wsock;
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
rsock = fdopen(sockfd, "r");
wsock = fdopen(sockfd, "w");
writeData->wsock = wsock;
readData->rsock = rsock;
writeData->sockfd = sockfd;
readData->sockfd = sockfd;
pthread_create(&write, NULL, writeProcess, (void*)writeData);
pthread_create(&read, NULL, readProcess, (void*)readData);
pthread_join(write, NULL);
pthread_join(read, NULL);
}
void *writeProcess(void *writeData)
{
FILE *wsock = ((writeStruct*)writeData)->wsock;
int sockfd = ((writeStruct*)writeData)->sockfd;
int success = 0;
char *buf = malloc(sizeof(char) * MAXDATASIZE);
while(fgets(buf, MAXDATASIZE, stdin) != NULL)
{
fputs(buf, wsock);
fflush(wsock);
}
fputs(buf, wsock);
free(buf);
shutdown(sockfd, SHUT_WR);
}
void *readProcess(void *readData)
{
FILE *rsock = ((readStruct*)readData)->rsock;
int sockfd = ((readStruct*)readData)->sockfd;
char *rcv, *rcvAux;
rcv = malloc(sizeof(char) * MAXDATASIZE);
rcvAux = malloc(sizeof(char) * MAXDATASIZE);
rcvAux = fgets(rcv, MAXDATASIZE, rsock);
while(rcvAux != NULL)
{
fflush(rsock);
numCharsRcv += strlen(rcv);
numLinesRcv++;
printf("%s", rcv);
rcvAux = fgets(rcv, MAXDATASIZE, rsock);
}
printf("%s", rcv);
free(rcv);
}
以及功能:
写入功能:
main()
{
writeStruct *writeData;
readStruct *readData;
writeData = malloc(sizeof(writeData));
readData = malloc(sizeof(readData));
pthread_t write;
pthread_t read;
FILE *rsock, *wsock;
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
rsock = fdopen(sockfd, "r");
wsock = fdopen(sockfd, "w");
writeData->wsock = wsock;
readData->rsock = rsock;
writeData->sockfd = sockfd;
readData->sockfd = sockfd;
pthread_create(&write, NULL, writeProcess, (void*)writeData);
pthread_create(&read, NULL, readProcess, (void*)readData);
pthread_join(write, NULL);
pthread_join(read, NULL);
}
void *writeProcess(void *writeData)
{
FILE *wsock = ((writeStruct*)writeData)->wsock;
int sockfd = ((writeStruct*)writeData)->sockfd;
int success = 0;
char *buf = malloc(sizeof(char) * MAXDATASIZE);
while(fgets(buf, MAXDATASIZE, stdin) != NULL)
{
fputs(buf, wsock);
fflush(wsock);
}
fputs(buf, wsock);
free(buf);
shutdown(sockfd, SHUT_WR);
}
void *readProcess(void *readData)
{
FILE *rsock = ((readStruct*)readData)->rsock;
int sockfd = ((readStruct*)readData)->sockfd;
char *rcv, *rcvAux;
rcv = malloc(sizeof(char) * MAXDATASIZE);
rcvAux = malloc(sizeof(char) * MAXDATASIZE);
rcvAux = fgets(rcv, MAXDATASIZE, rsock);
while(rcvAux != NULL)
{
fflush(rsock);
numCharsRcv += strlen(rcv);
numLinesRcv++;
printf("%s", rcv);
rcvAux = fgets(rcv, MAXDATASIZE, rsock);
}
printf("%s", rcv);
free(rcv);
}
读取功能:
main()
{
writeStruct *writeData;
readStruct *readData;
writeData = malloc(sizeof(writeData));
readData = malloc(sizeof(readData));
pthread_t write;
pthread_t read;
FILE *rsock, *wsock;
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
rsock = fdopen(sockfd, "r");
wsock = fdopen(sockfd, "w");
writeData->wsock = wsock;
readData->rsock = rsock;
writeData->sockfd = sockfd;
readData->sockfd = sockfd;
pthread_create(&write, NULL, writeProcess, (void*)writeData);
pthread_create(&read, NULL, readProcess, (void*)readData);
pthread_join(write, NULL);
pthread_join(read, NULL);
}
void *writeProcess(void *writeData)
{
FILE *wsock = ((writeStruct*)writeData)->wsock;
int sockfd = ((writeStruct*)writeData)->sockfd;
int success = 0;
char *buf = malloc(sizeof(char) * MAXDATASIZE);
while(fgets(buf, MAXDATASIZE, stdin) != NULL)
{
fputs(buf, wsock);
fflush(wsock);
}
fputs(buf, wsock);
free(buf);
shutdown(sockfd, SHUT_WR);
}
void *readProcess(void *readData)
{
FILE *rsock = ((readStruct*)readData)->rsock;
int sockfd = ((readStruct*)readData)->sockfd;
char *rcv, *rcvAux;
rcv = malloc(sizeof(char) * MAXDATASIZE);
rcvAux = malloc(sizeof(char) * MAXDATASIZE);
rcvAux = fgets(rcv, MAXDATASIZE, rsock);
while(rcvAux != NULL)
{
fflush(rsock);
numCharsRcv += strlen(rcv);
numLinesRcv++;
printf("%s", rcv);
rcvAux = fgets(rcv, MAXDATASIZE, rsock);
}
printf("%s", rcv);
free(rcv);
}
writeProcess()工作正常,但readProcess()工作不正常,显然rsock得到了一个无效的内存地址,我得到了分段错误
对不起,我遗漏了部分代码,可能会很长 实际上,我正在连接套接字,写函数正在工作,但是当它进入读函数时,文件指针失去了它的引用,至少我在用GDB调试时看到了这一点
在我添加线程之后,这个问题就开始出现了,当它在单个进程上运行时,它运行得很好我会首先检查fdopen()是否都返回了正确的值,如果没有返回,则检查bail。我会首先检查fdopen()是否都返回了正确的值,如果没有,请保释。下面的第1点很可能是造成细分错误的真正原因:
fgets
在存储字符串的末尾追加一个空字符。这意味着您必须传递MAXDATASIZE-1
,而不是MAXDATASIZE
,否则可能会发生溢出fgets
的返回值分配给rcvAux
,它本身指向您手动分配的另一个内存地址。在此分配之后,您将无法释放它,因为该分配内存的地址丢失
socket()
或fdopen()
的返回值。在退出应用程序之前,您不会关闭sockfd
fflush
是未定义的行为
您的代码段也不显示任何
connect()
或bind()
+listen()
+accept()
。为了执行读和/或写操作,应首先连接套接字。检查每个操作的返回值会发现这一点。下面的第1点可能是分段错误的真正原因:
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
fgets
在存储字符串的末尾追加一个空字符。这意味着您必须传递MAXDATASIZE-1
,而不是MAXDATASIZE
,否则可能会发生溢出fgets
的返回值分配给rcvAux
,它本身指向您手动分配的另一个内存地址。在此分配之后,您将无法释放它,因为该分配内存的地址丢失
socket()
或fdopen()
的返回值。在退出应用程序之前,您不会关闭sockfd
fflush
是未定义的行为
您的代码段也不显示任何connect()
或bind()
+listen()
+accept()
。为了执行读和/或写操作,应首先连接套接字。检查每个操作的返回值会发现这一点
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
上述操作将创建一个断开连接的TCP套接字
rsock = fdopen(sockfd, "r");
wsock = fdopen(sockfd, "w");
它们打开与两个功能异常的文件*
相同的断开的插座
首先需要两个不同的连接插座
如果你发布的代码是一个完整的程序,我看不出它应该如何工作。读卡器和写卡器都以fgets()
开始,这将永远阻止它们,因为没有数据
上述操作将创建一个断开连接的TCP套接字
rsock = fdopen(sockfd, "r");
wsock = fdopen(sockfd, "w");
它们打开与两个功能异常的文件*
相同的断开的插座
首先需要两个不同的连接插座
如果你发布的代码是一个完整的程序,我看不出它应该如何工作。读写器都从
fgets()
开始,这将永远阻止它们,因为没有数据。首先,对打开读取的文件调用fflush
是未定义的行为。。。即使它没有可怕的崩溃,它也不会做你想做的事。谁教你这样使用fflush
的?@R..:说得好!但是,我认为它设置了errno
(EBADF?)。不确定它是否真的没有定义。无论如何,我认为这给出了一个真正的答案。7.19.5.2:“如果流指向一个输出流或一个更新流,其中没有输入最新的操作,则fflush函数会导致将该流的任何未写入数据发送到主机环境中写入文件;否则,行为是未定义的。”@R..:oh,我错了:)谢谢你查找!!首先,对打开读取的文件调用fflush
是未定义的行为。。。即使它没有可怕的崩溃,它也不会做你想做的事。谁教你这样使用fflush
的?@R..:说得好!但是,我认为它设置了errno
(EBADF?)。不确定它是否真的没有定义。无论如何,我认为这给出了一个真正的答案。7.19.5.2:“如果流指向一个输出流或一个更新流,其中没有输入最新的操作,则fflush函数会导致将该流的任何未写入数据发送到主机环境中写入文件;否则,行为是未定义的。”@R..:oh,我错了:)谢谢你查找!!即使在可写文件描述符上,fflush
如果处于“读取模式”(如果最后一个操作是读取),也是UB。和switc