recvform 非阻塞
时间: 2023-10-09 10:10:44 浏览: 32
recvform 是一个自定义的函数,不是标准库中的函数。因此,它是否阻塞取决于它的实现方式。如果该函数使用了阻塞式的套接字操作,那么它就是阻塞的,如果使用了非阻塞式的套接字操作,那么它就是非阻塞的。
一般来说,在使用套接字时,可以通过设置套接字选项来控制是否使用阻塞式的操作。对于非阻塞式的套接字操作,可以使用 select、poll 或 epoll 等函数来进行异步的事件监听和处理。这些函数可以帮助我们在不阻塞主线程的情况下进行网络通信。
相关问题
recvform函数的用法
recvfrom函数是一个系统调用,用于从指定的套接字接收数据。它的函数声明如下:
```c
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
```
其中,sockfd表示要接收数据的套接字文件描述符;buf是指向接收缓冲区的指针,用于存储接收到的数据;len表示接收缓冲区的大小;flags参数用于指定接收数据时的特殊选项;src_addr是一个指向sockaddr结构体的指针,用于存储发送端的地址信息;addrlen是指向整数变量的指针,用于存储src_addr结构体的长度。
recvfrom函数的返回值是接收到的数据的字节数。如果返回了0,表示对端已经关闭了连接;如果返回了-1,表示出现了错误,可以通过errno变量获取具体的错误信息。
在使用recvfrom函数接收数据时,需要注意以下几点:
1. 接收缓冲区的大小应该足够大,以容纳接收到的数据。
2. 在使用recvfrom函数之前,需要先使用bind函数将套接字绑定到本地地址上。
3. 在调用recvfrom函数之前,需要指定src_addr和addrlen参数的初始值。在函数执行完毕后,这两个参数会被修改为发送端的实际地址信息。
计算机网络ping的C语言代码
以下是计算机网络中ping的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#define PACKET_SIZE 4096
#define TIMEOUT 4
#define MAX_NO_PACKETS 3
unsigned short checksum(void *b, int len)
{
unsigned short *buf = b;
unsigned int sum=0;
unsigned short result;
for ( sum = 0; len > 1; len -= 2 )
sum += *buf++ ;
if ( len == 1 )
sum += *(unsigned char*)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
int pack(int pack_no, char *sendpacket)
{
int i, packsize;
struct icmp *icmp;
struct timeval *tval;
icmp = (struct icmp*)sendpacket;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_seq = pack_no;
icmp->icmp_id = getpid();
packsize = 8 + 56;
tval = (struct timeval*)icmp->icmp_data;
gettimeofday(tval, NULL);
icmp->icmp_cksum = checksum(sendpacket, packsize);
return packsize;
}
int unpack(char *buf, int len, char *addr)
{
int i, iphdrlen, rtt;
struct ip *ip;
struct icmp *icmp;
struct timeval *tvsend, tvrecv, tvresult;
ip = (struct ip*)buf;
iphdrlen = ip->ip_hl << 2;
icmp = (struct icmp*)(buf + iphdrlen);
len -= iphdrlen;
if ( len < 8 )
{
printf("ICMP packets\'s length is less than 8\n");
return -1;
}
if ( (icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == getpid()))
{
tvsend = (struct timeval*)icmp->icmp_data;
gettimeofday(&tvrecv, NULL);
tvresult = tvsub(tvrecv, *tvsend);
rtt = tvresult.tv_sec * 1000 + tvresult.tv_usec / 1000;
printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%d ms\n", len, addr, icmp->icmp_seq, ip->ip_ttl, rtt);
return 0;
}
else
return -1;
}
struct timeval tvsub(struct timeval timeval1, struct timeval timeval2)
{
struct timeval result;
result.tv_sec = timeval1.tv_sec - timeval2.tv_sec;
result.tv_usec = timeval1.tv_usec - timeval2.tv_usec;
if (result.tv_usec < 0)
{
--result.tv_sec;
result.tv_usec += 1000000;
}
return result;
}
int Ping(char *ipaddress)
{
struct hostent *host;
struct icmp sendicmp;
struct sockaddr_in from;
struct sockaddr_in to;
int from_len = 0;
int sockfd = 0, nsend = 0, nreceived = 0, i = 0, packet_no = 0;
char sendpacket[PACKET_SIZE] = {0};
char recvbuf[PACKET_SIZE] = {0};
memset(&from, 0, sizeof(from));
memset(&to, 0, sizeof(to));
if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("socket error");
return -1;
}
setuid(getuid());
bzero(&sendicmp, sizeof(sendicmp));
to.sin_family = AF_INET;
if ( inet_addr(ipaddress) == INADDR_NONE )
{
if ((host = gethostbyname(ipaddress)) == NULL)
{
perror("gethostbyname error");
return -1;
}
memcpy(&to.sin_addr, host->h_addr, host->h_length);
}
else
to.sin_addr.s_addr = inet_addr(ipaddress);
printf("Ping %s ...\n", ipaddress);
for ( i = 0; i < MAX_NO_PACKETS; i++)
{
nsend = pack(packet_no++, sendpacket);
if ( sendto(sockfd, sendpacket, nsend, 0, (struct sockaddr*)&to, sizeof(to)) < 0 )
{
perror("sendto error");
continue;
}
nreceived++;
if ( recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&from, &from_len) < 0 )
{
perror("recvform error");
continue;
}
if ( unpack(recvbuf, sizeof(recvbuf), inet_ntoa(from.sin_addr)) == -1 )
continue;
sleep(1);
}
printf("Ping statistics for %s:\n", ipaddress);
printf("\tPackets: Sent = %d, Received = %d, Lost = %d(%d%% lost)\n", packet_no, nreceived, (packet_no - nreceived), ((packet_no - nreceived) * 100) / packet_no);
close(sockfd);
return 0;
}
int main(int argc, char *argv[])
{
if ( argc < 2 )
{
printf("Usage: %s IP\n", argv[0]);
return -1;
}
Ping(argv[1]);
return 0;
}
```
注意:此代码需要在 Linux 或 Mac 上编译运行,Windows 上需要进行一些修改才能编译运行。