Linux C套接字:在recv调用时被阻止
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Linux C套接字:在recv调用时被阻止,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4056字,纯文字阅读大概需要6分钟。
内容图文
在我的应用程序中,我为简单的http服务器创建了一个线程,然后从我的应用程序中尝试连接到http服务器,但是在recv调用中控件被阻止/挂起.
但是,如果尝试使用linux GET命令连接到应用程序的http服务器,则我将成功连接到http服务器.
据我对谷歌搜索的了解,我发现这不是正确的方法.
但是,如果要执行此操作,则应以什么方式创建套接字,以便可以从应用程序内部连接http服务器.
以下是我的http服务器套接字的创建方式
pthread_create(&pt_server, NULL, http_srvr, NULL);
//http server handler
void *http_server()
{
int sockfd, new_fd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
socklen_t sin_size;
struct sigaction sa;
int yes=1;
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(HTTP_PORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1)
{
perror("bind");
exit(1);
}
printf("Listening to sockets\n");
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,&sin_size)) == -1)
{
perror("accept");
continue;
}
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
handle_connection(new_fd);
}
}
以下是我如何将http POST到我的http服务器
/* create socket */
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return ERRSOCK;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
/* connect to server */
if (connect(s, &server, sizeof(server)) < 0)
ret=ERRCONN;
else {
if (pfd) *pfd=s;
/* create header */
if (proxy) {
sprintf(header,
"%s http://%.128s:%d/%.256s HTTP/1.0\015\012User-Agent: %s\015\012%s\015\012",
command,
http_server1,
http_port,
url,
http_user_agent,
additional_header
);
} else {
sprintf(header,
"%s /%.256s HTTP/1.0\015\012User-Agent: %s\015\012%s\015\012",
command,
url,
http_user_agent,
additional_header
);
}
hlg=strlen(header);
/* send header */
if (send(s,header,hlg,0)!=hlg)
ret= ERRWRHD;
/* send data */
else if (length && data && (send(s,data,length,0)!=length) )
ret= ERRWRDT;
else {
/* read result & check */
ret=http_read_line(s,header,MAXBUF-1);
以下是http_read_line的内容,并且在此函数中,recv调用被阻止
static int http_read_line (fd,buffer,max)
int fd; /* file descriptor to read from */
char *buffer; /* placeholder for data */
int max; /* max number of bytes to read */
{ /* not efficient on long lines (multiple unbuffered 1 char reads) */
int n=0;
while (n<max) {
if (recv(fd,buffer,1,0)!=1) {
n= -n;
break;
}
n++;
if (*buffer=='\015') continue; /* ignore CR */
if (*buffer=='\012') break; /* LF is the separator */
buffer++;
}
*buffer=0;
return n;
}
解决方法:
您已经告诉“在我的应用程序中,我为一个简单的http服务器创建了一个线程,然后在我的应用程序中
我试图连接到http服务器,但是在recv调用中控件被阻止/挂起.”
这意味着recv永远不会返回0.现在,当recv函数将
返回0? ->何时获得TCP FIN段.看来您的服务器永远不会
向客户端发送TCP FIN段.
这里最有可能的原因是,您的客户端代码需要修改.
您正在从客户端发送数据,但是从不发送FIN,
所以我认为您的服务器功能将永远持续下去,并且它并没有
发送了FIN.这使得recv永远等待.
在当前代码中,解决方法可能是添加一行
else {
/*Send the FIN segment, but we can still read the socket*/
shutdown(s, SHUT_WR);
/* read result & check */
ret=http_read_line(s,header,MAXBUF-1);
在这种情况下,关闭功能将发送TCP FIN,并且服务器功能可以返回,然后可能会进行适当的关闭.
并在适当的关闭时间内,客户端将收到来自服务器的FIN.这将使recv返回0,而不是永远被阻塞.
现在,如果您想继续从客户端进行任何进一步的数据传输,则需要再次连接,或者可能需要使用一些不同的算法.
我希望我的解释可以帮助解决当前问题.
内容总结
以上是互联网集市为您收集整理的Linux C套接字:在recv调用时被阻止全部内容,希望文章能够帮你解决Linux C套接字:在recv调用时被阻止所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。