【发布时间】:2011-09-14 20:16:28
【问题描述】:
我正在创建一个服务器/客户端回显程序。客户端读取一个字符串,发送到服务器,服务器将字符串返回给客户端。
数据结构:
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);
}
碰巧 writeProcess() 工作正常,但 readProcess() 没有,显然 rsock 获得了无效的内存地址,我得到了 Segmentation Fault。
对不起,我省略了部分代码,会很长。
实际上,我正在连接套接字并且写入函数正在工作,但是当它进入读取函数时,文件指针丢失了它的引用,至少我在使用 GDB 调试时已经看到了这一点。
这个问题在我添加线程后就开始出现了,当它在单个进程上运行时它工作得很好
【问题讨论】:
-
一方面,在打开读取的文件上调用
fflush是未定义的行为......即使它没有严重崩溃,它也不会做你想做的事。谁教你这样使用fflush? -
@R..:好点子!但是,我相信它设置了
errno(EBADF?)。不确定它是否真的未定义。无论如何,我认为这是一个真正的答案。 -
7.19.5.2:“如果流指向输出流或更新流,其中未输入最近的操作,则 fflush 函数会导致该流的任何未写入数据被传递到主机要写入文件的环境;否则,行为未定义。"
-
@R..: 哦,我错了 :) 感谢您查找!