linux socket编程 双线程同时读写缓冲流时为什么fprintf被阻塞了
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
char *first_msg = "USER user * * :name\r\n", *second_msg = "NICK verylongnickname\r\n";
int connect_to_server(char*, int)
void *thread_send(FILE*);
void *thread_recv(FILE*);
main()
{
char *server = "irc.freenode.net";
int port = 6667;
int fd;
FILE *fp_send, *fp_recv;
pthread_t thread;
if ( (fd = connect_to_server(server, port)) == -1 )
return 1;
fp_recv = fdopen(fd, "r");
fp_send = fdopen(fd, "w");
pthread_create(&thread, NULL, thread_recv, fp_recv);
pthread_create(&thread, NULL, thread_send, fp_send);
while (1)
sleep(1);
}
void *thread_recv(FILE *fp)
{
char buf[BUFSIZ];
while (1) {
fgets(buf, BUFSIZ, fp);
printf(buf);
}
}
void *thread_send(FILE *fp)
{
fprintf(fp, first_msg);
fprintf(fp, second_msg);
}
int connect_to_server(char *servname, int portnum)
{
int fd_sock;
struct hostent *servp;
struct sockaddr_in servaddr;
if ( (fd_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
return -1;
bzero((char*)&servaddr, sizeof(struct sockaddr_in));
if ( (servp = gethostbyname(servname)) == NULL )
return -1;
bcopy((char*)servp->h_addr, (char*)&servaddr.sin_addr, servp->h_length);
servaddr.sin_port = htons(portnum);
servaddr.sin_family = AF_INET;
if ( connect(fd_sock, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)) == -1 )
return -1;
return fd_sock;
}我以一个irc服务器来测试。编译运行了一下发现问题:发送线程thread_send被阻塞在了fprintf(fp, first_msg);这一句,而接收线程可以正常收到服务器的信息并打印出来(其中没有登录的回应,可见fprintf确实没发送出去)。
如果我仅在以一个单线程进行流读写,先fprintf发送登录报文,然后再fgets接收服务器应答,这样的话一切都没问题,IRC报文可以被发送出去,因为我可以看到服务器发回了有关登录的应答;
如果我把上面的流操作函数换成无缓冲读写,即fprintf换成write,fgets换成read,然后其他一切不变,即仍然是多线程,那么我也可以正常收到服务器的登录信息(说面write发送成功了)
因此我猜测是fprintf在对流写入时被fgets的流读取操作给阻塞了。我搜索了一下,对socket流同时读写的办法,有的只说设置为异步,但我man socket看了一下没看到有关异步设置的信息啊?还有的说需要先fflush,或者以"a+"方式打开socket文件描述符,然后以这个文件指针来读写,都试过了但还是没用。。。。
虽然用read和write肯定是没问题了,但弄不明白为什么无法用缓冲流读写总是有个疙瘩。。。第一次发帖求助,这里先谢谢各位!
相关推荐
Linux C语言实现TCP文件传输:从Socket编程到协议设计实战
网络编程是构建分布式系统的基石,其核心在于理解数据如何在网络中可靠传输。TCP协议通过三次握手、序列号确认、流量控制等机制,为应用层提供了面向连接的、可靠的字节流服务。在Linux环境下,Socket API是进行网络通信的标准接口,开发者通过创建Socket、绑定地址、监听连接、收发数据等系统调用,可以构建各种网络应用。这种底层控制能力对于实现高性能、低延迟的服务至关重要,尤其在资源受限或对效率有严苛要求的场景中,如嵌入式系统、高频交易或大规模并发服务器。基于TCP的应用层协议设计,例如采用“消息头+消息
Linux C语言TCP服务器开发:从Socket编程到并发处理实战
Socket编程是网络通信的基础,它通过操作系统提供的接口,实现了应用程序与网络协议栈之间的交互。其核心原理在于将复杂的网络数据包收发抽象为文件描述符的读写操作,从而简化了网络应用的开发。这一技术为构建高性能、可靠的网络服务提供了底层支持,广泛应用于Web服务器、游戏服务器、即时通讯等场景。本文以Linux环境下C语言实现TCP服务器为例,深入解析了从创建监听套接字、绑定地址端口,到处理连接请求和数据收发的完整流程。针对实际开发中的常见挑战,文章重点探讨了TCP粘包与拆包问题的解决方案,并对比了多进程、多线
产业园区如何提升科技企业技术需求匹配精准度?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。
Redis集群部署+Redis 链接地址放入Aollo +c#项目接入Redis
Redis集群部署+Redis 链接地址放入Aollo +c#项目接入Redis
cover_1793582495122.png
cover_1793582495122.png


