Linux下socket编程sendto命令详解 (linux socket sendto)
Linux下Socket编程sendto命令详解
在Linux下进行Socket编程需要掌握sendto函数的使用方法。sendto函数可以从一个已经打开的socket发送数据到指定的目的地址,可以是本地地址,也可以是远程地址。本文将详细介绍如何使用sendto函数。
sendto函数的基本用法
sendto函数的原型如下:
“`
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
“`
其中各个参数的意义如下:
– sockfd:已经打开的socket的描述符。
– buf:需要发送的数据。
– len:需要发送的数据的长度。
– flags:发送数据的标志。常见的标志有MSG_DONTWT和MSG_NOSIGNAL等。
– dest_addr:目的地址。可以是本地地址,也可以是远程地址。
– addrlen:目的地址的长度。
sendto函数的返回值为成功发送的字节数,发送失败返回-1,错误信息存储在errno中。
使用sendto函数发送数据
下面是一个简单的例子,演示如何使用sendto函数发送数据。该程序创建一个UDP socket,然后向指定的IP地址和端口发送一条信息。
“`c
#include
#include
#include
#include
#include
#include
#define IP_ADDR “localhost”
#define PORT 8080
#define BUF_SIZE 4096
int mn() {
int sockfd, ret;
char buf[BUF_SIZE];
struct sockaddr_in addr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
printf(“Create socket fled: %s\n”, strerror(errno));
exit(EXIT_FLURE);
}
printf(“Create socket success.\n”);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
inet_pton(AF_INET, IP_ADDR, &addr.sin_addr.s_addr);
addr.sin_port = htons(PORT);
strcpy(buf, “Hello, Socket”);
ret = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) {
printf(“Send message fled: %s\n”, strerror(errno));
close(sockfd);
exit(EXIT_FLURE);
}
printf(“Send message success.\n”);
close(sockfd);
return 0;
}
“`
该程序的流程如下:
1. 调用socket函数创建UDP socket;
2. 设置目的地址和端口;
3. 发送一条信息;
4. 关闭socket。
在sendto函数中,之一个参数为sockfd,表示与目标主机连接的socket描述符。第二个参数为要发送的数据,即buf。第三个参数为要发送数据的长度len。第四个参数flags设置为0,表示默认标志。第五个参数为目标地址,为一个指向目标socket地址结构的指针。第六个参数addrlen表示目标地址结构的长度,可以使用sizeof(struct sockaddr_in)。
在sendto函数执行成功后,sendto函数返回已发送的字节数。如果出现错误,sendto返回-1,错误信息存储在errno中。
sendto函数的选项
在使用sendto函数时,可以设置一些选项。常见的选项如下:
– MSG_DONTWT:非阻塞模式;
– MSG_NOSIGNAL:在对方关闭后不发送SIGPIPE信号;
– MSG_MORE:发送更多数据;
– MSG_CONFIRM:要求确认无误。
以MSG_DONTWT为例,下面是一个例子:
“`c
#include
#include
#include
#include
#include
#include
#include
#define IP_ADDR “localhost”
#define PORT 8080
#define BUF_SIZE 4096
int mn() {
int sockfd, ret;
char buf[BUF_SIZE];
struct sockaddr_in addr;
int flags;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
printf(“Create socket fled: %s\n”, strerror(errno));
exit(EXIT_FLURE);
}
printf(“Create socket success.\n”);
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
inet_pton(AF_INET, IP_ADDR, &addr.sin_addr.s_addr);
addr.sin_port = htons(PORT);
strcpy(buf, “Hello, Socket”);
ret = sendto(sockfd, buf, strlen(buf), MSG_DONTWT, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) {
printf(“Send message fled: %s\n”, strerror(errno));
close(sockfd);
exit(EXIT_FLURE);
}
printf(“Send message success.\n”);
close(sockfd);
return 0;
}
“`
在这个例子中,我们通过fcntl函数设置了socket为非阻塞模式,然后在sendto函数中加入了MSG_DONTWT选项。
在sendto函数中使用MSG_DONTWT选项时,如果socket处于阻塞模式下,则sendto函数会返回EAGN错误,否则立即返回。因此,我们需要将socket设置为非阻塞模式。在程序中,我们首先使用fcntl函数获取socket文件描述符的标志,然后通过F_SETFL选项更新socket的标志,将其设置为非阻塞模式。
相关问题拓展阅读:
- linux下如何用socket套接字来代替ping程序来检测终端网络连通性??急求(附代码加悬赏啊)
- 关于sendto的使用问题,总是显示network is unreachable
linux下如何用socket套接字来代替ping程序来检测终端网络连通性??急求(附代码加悬赏啊)
myping.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_SIZE 1024
char send_buf;
char recv_buf;
int nsend = 0,nrecv = 0;
int datalen = 56;
//统计结果
void statistics(int signum)
{
printf(“\n–PING statistics-\n”);
printf(“%d packets tranitted,%d recevid,%%%d lost\n”,nsend,nrecv,(nsend – nrecv)/nsend * 100);
exit(EXIT_SUCCESS);
}
/隐配/校验和算法
int calc_chsum(unsigned short *addr,int len)
{
int sum = 0,n = len;
unsigned short answer = 0;
unsigned short *p = addr;
//每两个字节相加
while(n > 1)
{
sum += *p ++;
n -= 2;
}
//处理数据大小是奇数,在最后一个字节后面补0
if(n == 1)
{
*((unsigned char *)&answer) = *(unsigned char *)p;
sum += answer;
}
//将得到的sum值的高樱携坦2字节和低2字节相加
sum = (sum >> 16) + (sum & 0xffff);
//处理溢出的情况
sum += sum >> 16;
answer = ~sum;
return answer;
}
int pack(int pack_num)
{
int packsize;
struct icmp *icmp;
struct timeval *tv;
icmp = (struct icmp *)send_buf;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_id = htons(getpid());
icmp->icmp_seq = htons(pack_num);
tv = (struct timeval *)icmp->icmp_data;
//记录发送时间
if(gettimeofday(tv,NULL) icmp_cksum = calc_chsum((unsigned short *)icmp,packsize);
return packsize;
}
int send_packet(int sockfd,struct sockaddr *paddr)
{
int packsize;
//将send_buf填上a
memset(send_buf,’a’,sizeof(send_buf));
nsend ++;
//打icmp包
packsize = pack(nsend);
if(sendto(sockfd,send_buf,packsize,0,paddr,sizeof(struct sockaddr)) tv_usec – tv_send->tv_usec tv_sec –;
tv_recv->tv_usec +=;
}
ts.tv_sec = tv_recv->tv_sec – tv_send->tv_sec;
ts.tv_usec = tv_recv->tv_usec – tv_send->tv_usec;
return ts;
}
int unpack(int len,struct timeval *tv_recv,struct sockaddr *paddr,char *ipname)
{
struct ip *ip;
struct icmp *icmp;
struct timeval *tv_send,ts;
int ip_head_len;
float rtt;
ip = (struct ip *)recv_buf;
ip_head_len = ip->ip_hl icmp_id) == getpid() && icmp->icmp_type == ICMP_ECHOREP)
{
nrecv ++;
tv_send = (struct timeval *)icmp->icmp_data;
ts = time_sub(tv_send,tv_recv);
rtt = ts.tv_sec * 1000 + (float)ts.tv_usec/1000;//以毫秒为单位
printf(“%d bytes from %s (%s):icmp_req = %d ttl=%d time=%.3fms.\n”,
len,ipname,inet_ntoa(((struct sockaddr_in *)paddr)->sin_addr),ntohs(icmp->icmp_seq),ip->ip_ttl,rtt);
}
return 0;
}
int recv_packet(int sockfd,char *ipname)
{
int addr_len ,n;
struct timeval tv;
struct sockaddr from_addr;
addr_len = sizeof(struct sockaddr);
if((n = recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,&from_addr,&addr_len)) p_proto)) h_addr,host->h_length);
}else{//ip地址
peer_addr.sin_addr.s_addr = netaddr;
}
//注册信号处理函数
signal(SIGALRM,statistics);
signal(SIGINT,statistics);
alarm(5);
//开始信息
printf(“PING %s(%s) %d bytes of data.\n”,argv,inet_ntoa(peer_addr.sin_addr),datalen);
//发送包文和接收报文
while(1)
{
send_packet(sockfd,(struct sockaddr *)&peer_addr);
recv_packet(sockfd,argv);
alarm(5);
sleep(1);
}
exit(EXIT_SUCCESS);
}
gcc -o myping myping.c
./myping 10.1.1.1
PING 10.1.1.1(10.1.1.1) 56 bytes of data.
64 bytes from 10.1.1.1 (10.1.1.1):icmp_req = 1 ttl=253 time=10.573ms.
64 bytes from 10.1.1.1 (10.1.1.1):icmp_req = 2 ttl=253 time=12.585ms.
64 bytes from 10.1.1.1 (10.1.1.1):icmp_req = 3 ttl=253 time=9.440ms.
64 bytes from 10.1.1.1 (10.1.1.1):icmp_req = 4 ttl=253 time=12.923ms.
关于sendto的使用问题,总是显示network is unreachable
两个疑点基梁:
1. 我所了解的linux中的socket编程中,在建立socket
套接字
之后,server需要listen,client需要connect之后才能建立连接,lz似乎少了这一步。请问lz用困桐的socket是应汪锋坦用在哪一个平台的?
2.. sendto函数中的(struct sockaddr *) &to6 这一项lz确认设置好了吗?在代码中确认一下
3. 如我理解有误,lz请追问。
linux socket sendto的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux socket sendto,Linux下socket编程sendto命令详解,linux下如何用socket套接字来代替ping程序来检测终端网络连通性??急求(附代码加悬赏啊),关于sendto的使用问题,总是显示network is unreachable的信息别忘了在本站进行查找喔。
香港服务器首选后浪云,2H2G首月10元开通。
后浪云(www.IDC.Net)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。