我需要用 C 语言进行套接字编程的帮助。我需要用 C 语言编写一个服务器客户端程序,其中两个 IP 在创建的套接字上相互通信。我成功地做到了这一点。但现在我想向套接字添加计时器。我做了一些研究,发现它可以通过 select() 来实现,其中我们给出超时值。我尝试这样做,但没有成功。在下面显示的代码中,我尝试连接到客户端并读取创建的新套接字 10 秒。如果客户端在这 10 秒内发送一些消息,服务器应该接收该消息并发回确认。如果没有,必须给出错误消息,指出超时。
我的服务器代码如下:
#include<stdio.h>
#include<unistd.h>
#include<sys/time.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdlib.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int a=1;
fd_set readfds,writefds;
int ready_for_reading,reading;
struct timeval time_out;
FD_ZERO(&readfds);
// FD_ZERO(&writefds);
FD_SET(a,&readfds);
time_out.tv_sec = 10; // 10 seconds
time_out.tv_usec = 0; // 0 milliseconds
// ready_for_reading=select(1,&readfds,NULL,NULL,&time_out);
int sockfd, newsockfd, portno,n,clilen;;
struct sockaddr_in serv_addr,cli_addr;
char buffer[256];
portno=atoi(argv[1]);
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
error("\nError creating socket");
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(portno);
serv_addr.sin_addr.s_addr=INADDR_ANY;
n=bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(n<0)
error("\nError binding socket");
listen(sockfd,5);
clilen=sizeof(cli_addr);
printf("\nAccept call reached");
newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen);
printf("\nnewSockfd=%d",newsockfd);
printf("\ntesting value:%d",sizeof(readfds));
if(newsockfd==-1)
error("\nError on accept");
// FD_SET(a,&readfds);
ready_for_reading=select(sizeof(readfds)*8,&readfds,NULL,NULL,&time_out);
printf("\nready_for_reading=%d",ready_for_reading);
if (ready_for_reading == -1)
{
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
}
else
{
if (ready_for_reading)
{
reading = read(newsockfd, buffer, 255);
printf("Read, %d bytes from input : %s \n", reading,buffer);
}
else
{
printf(" 10 Seconds are over - no data input \n");
return 0;
}
}
/* n=read(newsockfd,buffer,255);
if(n<0)
error("\nError in reading client's msg");
*/
printf("\nClient's msg is:%s\n",buffer);
n=write(newsockfd,"I got your message",25);
if(n<0)
error("\nError on writing");
return 0;
}
select() 函数始终返回“0”。我需要这方面的帮助。 提前致谢, 理查德.
int a=1;
fd_set readfds,writefds;
int ready_for_reading,reading;
struct timeval time_out;
FD_ZERO(&readfds);
// FD_ZERO(&writefds);
FD_SET(a,&readfds); // a?!
您正在选择文件描述符 1,stdout。您应该选择从
accept
返回的文件描述符。
对于您的特定问题,您可以使用
SO_RCVTIMEO
套接字选项。
#include <assert.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv_with_timeout (int s, void *buf, size_t len, int flags,
struct timeval *timeout)
{
if (timeout) {
ssize_t bytes;
int r;
struct timeval last;
socklen_t lastlen = sizeof(last);
r = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &last, &lastlen);
if (r < 0) return r;
r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, timeout, sizeof(*timeout));
if (r < 0) return r;
bytes = recv(s, buf, len, flags);
r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &last, lastlen);
assert(r == 0);
return bytes;
}
return recv(s, buf, len, flags);
}
来自手册页:
SO_RCVTIMEO
设置超时值,指定输入函数完成之前等待的最长时间。它接受一个 timeval 结构,其中包含秒数和微秒数,指定等待输入操作完成的时间限制。如果接收操作已经阻塞了这么长时间而没有接收到额外的数据,则如果没有接收到数据,它将返回部分计数或设置为 [EAGAIN] 或 [EWOULDBLOCK] 的 errno。该选项的默认值为零,这表示接收操作不会超时。该选项采用 timeval 结构。请注意,并非所有实现都允许设置此选项。