recvfrom 函数的问题
时间:2010-08-31
来源:互联网
第一次用网络编程,使用了原始套接字的UDP。想实现的功能是服务器接受到来自客户端的数据然后返回给客户端,但是会出现以下问题:
(1)在recvfrom函数接时,得到的客户端的地址信息(struct sockaddr_in client)中的端口号为0,以至于,服务器返回数据的sendto函数不能执行成功。
(2)只要服务器接收到来自客户端的信息,客户端就不停的在循环、不停的打印出消息,而且消息的内容始终是第一条的消息。
代码如下所示,请各位指正!谢谢!
复制代码
(1)在recvfrom函数接时,得到的客户端的地址信息(struct sockaddr_in client)中的端口号为0,以至于,服务器返回数据的sendto函数不能执行成功。
(2)只要服务器接收到来自客户端的信息,客户端就不停的在循环、不停的打印出消息,而且消息的内容始终是第一条的消息。
代码如下所示,请各位指正!谢谢!
- //头文件header.h
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <netdb.h>
-
- #include <sys/types.h>
-
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/udp.h>
-
- #include <sys/socket.h>
-
- #include <sys/wait.h>
-
- #include <unistd.h>
-
- #include <pthread.h>
- //#include <linux/ip.h>
-
- #define IP_HEAD_LEN 20 //IP header length
- #define UDP_HEAD_LEN 8 //UDP header length
- #define PACKET_LEN 1500 //Packet length(decided by ethnet packet length)
- #define UDP_LEN PACKET_LEN - IP_HEAD_LEN //UDP length(include UDP head and data)
- #define MSG_LEN UDP_LEN - UDP_HEAD_LEN //paylod length(data)
- #define SERVER_PORT 4567 //server default port
- #define CLIENT_PORT 4567 //client default port
- #define MAX_ROUTE_HOP 64 //Max route hops
- #define MAX_USER 5
- /*
- *user information structure
- */
- typedef struct user
- {
- int sockfd;
- struct sockaddr_in addr;
- }USER;
-
- /* Pseudo Header Structure */
- typedef struct psd_hdr //定义UDP/TCP伪报头
- {
- struct in_addr saddr; //源地址
- struct in_addr daddr; //目的地址
- unsigned char mbz; //全零
- unsigned char proto; //协议类型
- unsigned short len; //UDP/TCP长度
- }PSD_HEADER;
-
- /* UDP Header Structure */
- typedef struct _udphdr //定义UDP报头
- {
- unsigned short uh_sport; //16位源端口
- unsigned short uh_dport; //16位目的端口
- unsigned short uh_len; //16位长度
- unsigned short uh_sum; //16位校验和
- }UDP_HEADER;
-
- /* TCP Header Structure
- */
- typedef struct _tcphdr //定义TCP报头
- {
- unsigned short th_sport; //16位源端口
- unsigned short th_dport; //16位目的端口
- unsigned int th_seq; //32位序列号
- unsigned int th_ack; //32位确认号
- unsigned char th_lenres; //4位首部长度/4位保留字
- unsigned char th_flag; //6位标志位
- unsigned short th_win; //16位窗口大小
- unsigned short th_sum; //16位校验和
- unsigned short th_urp; //16位紧急数据偏移量
- }TCP_HEADER;
-
- /*IP HEADER Structure
- */
- typedef struct _iphdr //定义IP报头
- {
- unsigned char h_lenver; //version and header len
- unsigned char tos; //type of service 8bit
- unsigned short t_len; //total length 16bit
- unsigned short id; //identification 16bit
- unsigned short off;
- unsigned char ttl;
- unsigned char proto;
- unsigned short sum;
- struct in_addr srcIP;
- struct in_addr dstIP;
- }IP_HEADER;
-
- //服务器
- #include "header.h"
-
- static unsigned short checksum(int numwords, unsigned short *buff);
- void RemovHead(int type, char *buf);
- struct sockaddr_in user[MAX_USER]; //user structure array
-
- int main()
- {
- int sockfd,i; //i用作循环
- struct sockaddr_in server,client;
- struct hostent *ht;
- IP_HEADER iphead;
- UDP_HEADER udphead;
- PSD_HEADER psdhead;
- struct in_addr my_addr;
-
- struct in_addr serv_addr;
-
- char hostname[20],qstr[] = "quit";
- char msg_tx[PACKET_LEN],buf[PACKET_LEN]; /*message and buffer to send */
- char msg_rx[PACKET_LEN];
- int on=1;
- int add_len = sizeof(struct sockaddr);
-
- for(i=0; i<MAX_USER; i++)
- {
- user[i].sin_addr.s_addr = 0;
- }
-
- printf("\nEnter the server's IP:\n");
- scanf("%s",hostname);
-
- //创建原始套接字
- if((sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_UDP)) == -1)
- {
- perror("socket");
- exit(1);
- }
-
- //设置套接字选项
- if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,&on, sizeof(on)) < 0)
- {
- printf("setsockopt error!\n");
- close(sockfd);
- exit(1);
- }
-
- //获得host信息
- if((ht = gethostbyname(hostname)) == NULL)
- {
- perror("gethostbyname");
- exit(1);
- }
-
- //填充sockaddr_in结构体
- memcpy(&server.sin_addr,ht->h_addr,ht->h_length);
- server.sin_family = AF_INET;
- server.sin_port=htons(SERVER_PORT);
- bzero(&(server.sin_zero),8);
-
- //帮定套接字
- if(bind(sockfd, (struct sockaddr*)&server,sizeof(server)) < 0)
- {
- perror("bind");
- exit(1);
- }
- printf("socket success...\n");
-
- //ip头部填充
- iphead.h_lenver = (4<<4|sizeof(IP_HEADER)/sizeof(unsigned long));
- iphead.tos = 0;
- iphead.id = htons((unsigned short)rand());
- iphead.off = 0;
- iphead.ttl = MAX_ROUTE_HOP;
- iphead.proto = IPPROTO_UDP;
- iphead.sum = 0;
- iphead.srcIP = server.sin_addr; //测试用的环路地址127.0.0.1
- iphead.dstIP = server.sin_addr;
-
- //udp头部填充
- udphead.uh_sport = htons(CLIENT_PORT);
- udphead.uh_dport = htons(SERVER_PORT);
- udphead.uh_sum = 0;
-
- //udp伪首部填充
- psdhead.saddr = iphead.srcIP;
- psdhead.daddr = iphead.dstIP;
- psdhead.mbz = 0;
- psdhead.proto = iphead.proto;
-
- //接收消息
- printf("You can receive data now!\n");
- int len = -1;
- int msg_rx_num = 0;
- int msg_tx_num = 0;
-
- IP_HEADER *pip = (IP_HEADER*)malloc(sizeof(IP_HEADER));
- UDP_HEADER *pudp = (UDP_HEADER*)malloc(sizeof(UDP_HEADER));
- while(1)
- {
- //usleep(2000000);
- memset(msg_rx, 0, MSG_LEN);
-
- memset(buf, 0, MSG_LEN);
- len = recvfrom(sockfd,msg_rx,sizeof(msg_rx),0,(struct sockaddr*)&client,&add_len);
- if(len < 0)
- {
- printf("不是来自rawclient的消息");
- }
- else
- {
- printf("\nsockfd =%d----------------------------------------------------\n",sockfd);
- printf("\n客户端口:%d",client.sin_port);
- printf("\t客户IP:%d",client.sin_addr.s_addr);
-
- /*打印、调试============================================================*/
- pip = (IP_HEADER*)msg_rx;
- pudp = (UDP_HEADER*)(msg_rx + pip->t_len);
-
- printf("协议:%d,校验和:%d\n",pip->proto,pip->sum);
- printf("源地址:%d",pip->srcIP.s_addr);
- printf("\t目的地址:%d\n",pip->dstIP.s_addr);
- printf("源端口:%d,目的端口:%d,长度:%d\n",
- ntohs(pudp->uh_sport),ntohs(pudp->uh_dport),ntohs(pudp->uh_len));
-
- char tmp[MSG_LEN];
- memcpy(buf,msg_rx+sizeof(IP_HEADER)+sizeof(UDP_HEADER),sizeof(buf));
- printf("接收到第%d条消息:%s\n",msg_rx_num++,buf);
-
- //转发=========================
- char *ptr = msg_tx;
- memset(msg_tx, 0, MSG_LEN);
- iphead.t_len = htons(sizeof(IP_HEADER)+sizeof(UDP_HEADER)+strlen(buf));
- udphead.uh_len = htons(sizeof(UDP_HEADER)+strlen(buf));
- psdhead.len = udphead.uh_len;
-
- //组包、发送
- memcpy(ptr,&iphead,sizeof(IP_HEADER));
- ptr += sizeof(IP_HEADER);
- memcpy(ptr,&udphead,sizeof(UDP_HEADER));
- ptr += sizeof(UDP_HEADER);
- memcpy(ptr,buf,strlen(buf));
- usleep(2000000);
- int len=-1;
- if ((len = sendto(sockfd,msg_tx,PACKET_LEN,0,(struct sockaddr *)&client,add_len)) < 0)
- {
- perror("sendto");
- }
- }
- printf("\n=====================================================================\n");
-
- }
- free(pudp);
- pip = NULL;
- free(pip);
- pudp = NULL;
-
- close(sockfd);
-
- }
-
-
- //客户端
- #include "header.h"
- int main()
- {
- int sockfd;
- struct sockaddr_in server,client;
- struct hostent *ht;
- IP_HEADER *iphead = (IP_HEADER*)malloc(sizeof(IP_HEADER));
- UDP_HEADER *udphead = (UDP_HEADER*)malloc(sizeof(UDP_HEADER));
- PSD_HEADER *psdhead = (PSD_HEADER*)malloc(sizeof(PSD_HEADER));
- struct in_addr my_addr;
-
- struct in_addr serv_addr;
-
- char hostname[20],qstr[] = "quit";
- char msg_tx[MSG_LEN];
- char msg_rx[MSG_LEN],buf[PACKET_LEN]; /*message and buffer to send */
- int on=1;
- int add_len = sizeof(struct sockaddr);
- //pthread_t tid;
-
- printf("Enter the server's IP:\n");
- scanf("%s",hostname);
-
- //create a socket for communicatting
- if((sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_UDP)) == -1)
- {
- perror("socket");
- exit(1);
- }
-
- //set the socket option
- if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,&on, sizeof(on)) < 0)
- {
- printf("setsockopt error!");
- close(sockfd);
- exit(1);
- }
-
- //get host form IP address
- if((ht = gethostbyname(hostname)) == NULL)
- {
- perror("gethostbyname");
- exit(1);
- }
- printf("socket success...");
-
- //copy IP of server to server's struct
- memcpy(&server.sin_addr,ht->h_addr,ht->h_length);
-
- server.sin_family = AF_INET;
-
- server.sin_port=htons(SERVER_PORT);
- bzero(&(server.sin_addr),8);
-
- memset(buf, 0x00, MSG_LEN);
-
-
- //ip header
-
- iphead->h_lenver = (4<<4|sizeof(IP_HEADER)/sizeof(unsigned long));
-
- iphead->tos = 0;
-
- iphead->id = htons((unsigned short)rand());
-
- iphead->off = 0;
-
- iphead->ttl = MAX_ROUTE_HOP;
-
- iphead->proto = IPPROTO_UDP;
-
- iphead->sum = 0;
-
- iphead->srcIP = server.sin_addr; //测试用的环路地址127.0.0.1
-
- iphead->dstIP = server.sin_addr;
-
- //udp header
- udphead->uh_sport = htons(CLIENT_PORT);
- udphead->uh_dport = htons(SERVER_PORT);
- udphead->uh_sum = 0;
-
- //psd header
- psdhead->saddr = iphead->srcIP;
- psdhead->daddr = iphead->dstIP;
- psdhead->mbz = 0;
- psdhead->proto = iphead->proto;
- //psdhead->len = udphead->uh_len;
-
- //send message
- printf("\nYou can talk now!\n");
-
- int msg_tx_num = 0;
- int msg_rx_num = 0;
- printf("input msg_tx\n");
- scanf("%s",msg_tx);
- while(1)
- {
- char *ptr = buf;
- printf("input msg_tx\n");
- scanf("%s",msg_tx);
- memset(buf, 0x00, sizeof(buf));
- iphead->t_len = htons(sizeof(IP_HEADER)+sizeof(UDP_HEADER)+strlen(msg_tx));
- udphead->uh_len = htons(sizeof(UDP_HEADER)+strlen(msg_tx));
- psdhead->len = udphead->uh_len;
-
- //form a packet to send
- memcpy(ptr,iphead,sizeof(IP_HEADER));
- ptr += sizeof(IP_HEADER);
- memcpy(ptr,udphead,sizeof(UDP_HEADER));
- ptr += sizeof(UDP_HEADER);
- memcpy(ptr,msg_tx,strlen(msg_tx));
- int len=-1;
- if ((len =sendto(sockfd,buf,PACKET_LEN,0,(struct sockaddr *)(&server),sizeof(struct sockaddr))) < 0)
- {
- perror("sendto");
- }
- else
- {
- printf("\n发送:%d,%s\n",msg_tx_num++,msg_tx);
- /*打印消息,以便调试*/
- IP_HEADER *pip;
- UDP_HEADER *pudp;
- pip = (IP_HEADER*)buf;
- pudp = (UDP_HEADER*)(buf+20);
- printf("\n协议:%d,校验和:%d,源地址:%ld,目的地址:%ld\n",
- pip->proto,pip->sum,(long int)(pip->srcIP.s_addr),(long int)(pip->dstIP.s_addr));
- printf("源端口:%d,目的端口:%d,长度:%d\n",
- pudp->uh_sport,pudp->uh_dport,pudp->uh_len);
- }
-
- memset(buf,0x00,sizeof(buf));
- memset(msg_rx,0x00,sizeof(msg_rx));
- usleep(2000000);
- len = -1;
- if((len = recvfrom(sockfd,msg_rx,PACKET_LEN,0,(struct sockaddr*)(&server),&add_len)) > 0)
- {
- char tmp[MSG_LEN];
- memcpy(tmp,buf+sizeof(IP_HEADER)+sizeof(UDP_HEADER),MSG_LEN);
- printf("%s",tmp);
- }
- printf("\n=====================================================================\n");
- }
- }
作者: whyliyi 发布时间: 2010-08-31
(gdb) p client
$3 = {sin_family = 2, sin_port = 0, sin_addr = {s_addr = 57701834},
sin_zero = "\000\000\000\000\000\000\000"}
上边是单步调试的结果,sin_port = 0,这是为什么?
$3 = {sin_family = 2, sin_port = 0, sin_addr = {s_addr = 57701834},
sin_zero = "\000\000\000\000\000\000\000"}
上边是单步调试的结果,sin_port = 0,这是为什么?
作者: whyliyi 发布时间: 2010-08-31
代码好长啊!
作者: ecjtubaowp 发布时间: 2010-08-31
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28