C 使用线程时printf无法正常工作
您好,在使用线程时,printf有一个小问题。问题是终端稍晚打印一条printf语句,这条语句应该更早打印。这就是我面对这个问题的部分C 使用线程时printf无法正常工作,c,multithreading,posix,C,Multithreading,Posix,您好,在使用线程时,printf有一个小问题。问题是终端稍晚打印一条printf语句,这条语句应该更早打印。这就是我面对这个问题的部分 . . . while(1){ printf("waiting for a connection\n"); csock = (int*)malloc(sizeof(int)); if((*csock = accept( hsock, (struct sockaddr*)&sadr, &
.
.
.
while(1){
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (struct sockaddr*)&sadr, &addr_size))!= -1){
printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
client_counter++;
pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
}
else{
fprintf(stderr, "Error accepting %d\n", errno);
}
}// end while
.
.
.
这就是线程使用的函数
void* SocketHandler(void* lp){
int *csock = (int*)lp;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
char* str_exit="exit";
while(1){
memset(buffer, 0, buffer_len);
if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
exit(0);
}
if(strcmp(buffer,str_exit)==0){
break;
}
printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
strcat(buffer, " SERVER ECHO");
if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){
fprintf(stderr, "Error sending data %d\n", errno);
exit(0);
}
//printf("Sent bytes %d Sent String %s\n", bytecount,buffer);
}
printf("Client disconnected\n");
free(csock);
return 0;
}
每当客户端(线程)连接到服务器时,输出都是这样的
waiting for a connection
---------------------
Received connection from 127.0.0.1
waiting for a connection
Client disconnected
---------------------
Received connection from 127.0.0.1
waiting for a connection
Client disconnected
当第一个客户端连接时,输出正常工作,但当第二个客户端连接字符串时,“等待连接”
出现在“已接收连接”
之后。它应该以相反的方式工作。不管怎样,如果你能帮助我并感谢我,我会很高兴的
setbuf(stdout,NULL);
setbuf(stderr,NULL);
关闭输出缓冲。printf不是可重入的,因此它使用全局锁进行同步。
缓冲输出时,一个线程可能不会在另一个线程开始打印之前释放其锁
在进行多线程处理时,始终建议或手动调用
关闭输出缓冲。printf不是可重入的,因此它使用全局锁进行同步。
缓冲输出时,一个线程可能不会在另一个线程开始打印之前释放其锁
在多线程处理时,建议始终或手动调用如果混合使用stderr和stdout,除非每次使用后刷新,否则无法期望正确的顺序。多线程的情况变得更加复杂(刷新是不够的),因此我认为您应该选择一个流(stdout或stderr)并坚持使用它。如果您混合使用stderr和stdout,除非每次使用后都刷新,否则无法期望正确的顺序。多线程的情况变得更加复杂(刷新是不够的),因此我认为您应该选择一个流(stdout或stderr)并坚持使用它。没有问题。除了第一次进入循环外,“等待连接”将是客户端连接后accept线程最后打印的内容
换句话说,这个循环在accept()调用时开始/结束,第一次输入时除外。这是第一次通过“异常”,而不是后续循环。没有问题。除了第一次进入循环外,“等待连接”将是客户端连接后accept线程最后打印的内容 换句话说,这个循环在accept()调用时开始/结束,第一次输入时除外。这是第一次出现“异常”,而不是随后的循环。没有问题(或者至少你所描述的不是问题)。以下是一些带注释的输出:
waiting for a connection # 1
--------------------- # 1
Received connection from 127.0.0.1 # 1
waiting for a connection # 2
Client disconnected # thread handling connection 1
--------------------- # 2
Received connection from 127.0.0.1 # 2
waiting for a connection # 3
Client disconnected # thread handling connection 2
如果稍微更改while循环,则输出将成为自记录:
int i = 0;
while(1) {
printf("%d: waiting for a connection\n", i);
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (struct sockaddr*)&sadr, &addr_size))!= -1) {
printf("%d: ---------------------\n%d: Received connection from %s\n",
i, i, inet_ntoa(sadr.sin_addr));
client_counter++;
pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
}
else{
fprintf(stderr, "%d: Error accepting %d\n", i, errno);
}
++i;
}// end while
您可能希望为要打印的线程添加一个类似的ID—例如,不要传入表示套接字的单个int
,而是传入一个小结构,其中包含创建线程时的套接字和客户端计数器(或“i”或更有用的值)。没有问题(或者至少您描述的内容不是问题)。以下是一些带注释的输出:
waiting for a connection # 1
--------------------- # 1
Received connection from 127.0.0.1 # 1
waiting for a connection # 2
Client disconnected # thread handling connection 1
--------------------- # 2
Received connection from 127.0.0.1 # 2
waiting for a connection # 3
Client disconnected # thread handling connection 2
如果稍微更改while循环,则输出将成为自记录:
int i = 0;
while(1) {
printf("%d: waiting for a connection\n", i);
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (struct sockaddr*)&sadr, &addr_size))!= -1) {
printf("%d: ---------------------\n%d: Received connection from %s\n",
i, i, inet_ntoa(sadr.sin_addr));
client_counter++;
pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
}
else{
fprintf(stderr, "%d: Error accepting %d\n", i, errno);
}
++i;
}// end while
您可能希望为要打印的线程添加一个类似的ID—例如,不是传入表示套接字的单个int
,而是传入一个包含套接字和客户端计数器的小结构(或“i”或更有用的东西)创建线程时的值。您可能需要考虑fflush()
。您可能需要考虑和funlockfile()
。问题出在哪里?我看不到:waiting/received,waiting/received,waiting。这就是你编码它的方式,也是我期望的输出。accept线程启动,等待,然后接收两个连接,然后再等待另一个。@JonathanLeffler实际上把fflush(stdout)
放在printf的上面和下面(“正在等待连接”;
但输出仍然是相同的,因为输出没有问题。您可能需要考虑fflush()
。您可能需要考虑和funlockfile()
。问题出在哪里?我看不到:waiting/received,waiting/received,waiting。这就是你编码它的方式,也是我期望的输出。accept线程启动,等待,然后接收两个连接,然后再等待另一个。@JonathanLeffler实际上把fflush(stdout)
放在printf(“等待连接\n“;
但输出仍然是相同的,因为输出没有问题。我尝试在printf
语句的上方和下方调用fflush(stdout)
。但它们都不起作用..因为没有什么可修复的!我尝试调用fflush(stdout)
完全在printf
语句的上面和下面。但是它们都不起作用。因为没有什么需要修复的!有没有办法正确地使用它们?或者只使用其中一个是避免任何复杂化的唯一方法如果你想在它们可能引用相同的底层文件或终端时混合使用它们,你会得到中断输出(可能随机交错)。避免这种情况的唯一方法是创建自己的互斥锁,同时保护stdout和stderr,并在任何时候向其中一个写入时将其锁定。是否有办法正确使用这两个互斥锁?或者仅使用其中一个互斥锁是避免任何复杂化的唯一方法如果您希望在引用相同的底层文件或终端,您将得到损坏的输出(可能是随机交错的)。避免这种情况的唯一方法是创建自己的互斥锁,保护stdout和stderr,并在您想写入时锁定它