免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 12083 | 回复: 4
打印 上一主题 下一主题

求助,linux 网络多线程编程错误: Socket Error:Operation not permitted [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-09-11 03:21 |只看该作者 |倒序浏览
最近在做实验,一个程序中创建两个线程同时给一个ip主机发送模拟TCP数据包(只是发送和接收,不考虑TCP协议细节),可是当两个线程同时发送时就会产生错误,显示为 Socket Error:Operation not permitted,但是只用其中的一个线程发送的时候就没错,感觉是什么地方冲突了,但是自己的水平很低,不知道错误的原因,也不知道怎么解决,所以请高手指点,先谢谢了,源码如下:


#include <sys/socket.h>

#include <netinet/ip.h>

#include <netinet/in.h>

#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>

#include <errno.h>
#include <net/if.h>

#include <unistd.h>

#include <stdio.h>

#include <netdb.h>

#include <pthread.h>
#include <memory.h>

#include <unistd.h>
#include <fcntl.h>





#define  ETH_NAME    "eth0"

#define  DESTPORT    80  //destination port

#define  LOCALPORT   6666//local host
#define  BUFSIZE     1500//maxsimum bytes in every packet


pthread_t thread[2];
pthread_mutex_t send_mutex,time_mutex;




void send_tcp(int sockfd,struct sockaddr_in *saddr,struct sockaddr_in *daddr,int priority);

unsigned short check_sum(unsigned short *addr,int len);

void init_random()
{//通过urandom文件产生随机数
                unsigned int ticks;
                struct timeval tv;
                int fd;
                gettimeofday (&tv, NULL);
                ticks = tv.tv_sec + tv.tv_usec;
                fd = open ("/dev/urandom", O_RDONLY);
                if (fd > 0){
                                unsigned int r;
                                int i;
                                for (i = 0; i < 10240; i++){
                                                read (fd, &r, sizeof (r));
                                                ticks += r;
                                }
                                close (fd);
                }
                srand (ticks);
                printf("init finished ";

                }
unsigned int new_rand()
{//获得随机数
                int fd;
                unsigned int n = 0;
                fd = open ("/dev/urandom", O_RDONLY);
                if (fd > 0){
                                read (fd, &n, sizeof (n));
                }
                close (fd);
                return n;

}

inline int sendpkt_interval(int range)
{//连续发送数据包时相邻数据包之间的时间间隔
                int rdtime= new_rand()%range;
                return rdtime;
}

inline int randpktnum(int range)
{//一次连续发送数据包的个数
                int rdnum= new_rand()%range;
                return rdnum;
}


inline int wait_to_resendtime(int range)
{//等待下一波数据包的时间
                int rdnum= new_rand()%range;
                return rdnum;
}

inline int randBytes(int range)
{//每个数据包中的字节数,包括TCP头和IP头,不包括MAC头
                int rdnum= new_rand()%range;
                return rdnum;
}

void serial_sending(int sockfd,struct sockaddr_in *saddr,struct sockaddr_in *daddr,int priority,int packetsnum)
{//发送一串数据包
                int num=randpktnum( packetsnum );
                while(num-->0){
                                send_tcp(sockfd,saddr,daddr,priority);
                                usleep(sendpkt_interval(10000));
                }
}


void* packet_sender_0()

{//发包线程0

                int sock0;
                struct sockaddr_in saddr;

                struct sockaddr_in daddr;

                struct hostent *host;  
                struct ifreq ifr;

                int on=1;



                bzero(&saddr,sizeof(struct sockaddr_in));

                bzero(&daddr,sizeof(struct sockaddr_in));
                saddr.sin_family=AF_INET;

                daddr.sin_family=AF_INET;
                saddr.sin_port=htons(LOCALPORT);

                daddr.sin_port=htons(DESTPORT);


                host=gethostbyname("192.168.1.4";//设置目的主机ip

                daddr.sin_addr=*(struct in_addr*)(host-> h_addr_list[0]);

  
                if((sock0=socket(AF_INET,SOCK_RAW,IPPROTO_TCP) )<0)//create a TCP raw socket

                {

                        fprintf(stderr, "Socket Error:%s\n\a ",strerror(errno));

                        exit(1);

                }

                strncpy(ifr.ifr_name, ETH_NAME, IFNAMSIZ);
                ifr.ifr_name[IFNAMSIZ - 1] = 0;

      if (ioctl(sock0, SIOCGIFADDR, &ifr) < 0)//获取本机主机ip
                        {
            perror("ioctl";
            return;
                 }

      memcpy(&saddr, &ifr.ifr_addr, sizeof(saddr));//保存到saddr中

           setsockopt(sock0,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));//set socket option

           setuid(getpid());//no choice,only superuser can use raw socket

           while(1){
                                pthread_mutex_lock(&time_mutex);
                                sleep(wait_to_resendtime(5));
                                pthread_mutex_unlock(&time_mutex);

                                pthread_mutex_lock(&send_mutex);

                                serial_sending(sock0,&saddr,&daddr,0,300);
                                pthread_mutex_unlock(&send_mutex);
               }


}  

void* packet_sender_1()

{//发包线程1

                int sock1;
                struct sockaddr_in saddr;

                struct sockaddr_in daddr;

                struct hostent *host;  
                struct ifreq ifr;

                int on=1;



                bzero(&saddr,sizeof(struct sockaddr_in));

                bzero(&daddr,sizeof(struct sockaddr_in));
                saddr.sin_family=AF_INET;

                daddr.sin_family=AF_INET;
                saddr.sin_port=htons(LOCALPORT);

                daddr.sin_port=htons(DESTPORT);


                host=gethostbyname("192.168.1.4";//设置目的主机ip

                daddr.sin_addr=*(struct in_addr*)(host-> h_addr_list[0]);

  
                if((sock1=socket(AF_INET,SOCK_RAW,IPPROTO_TCP) )<0)//create a TCP raw socket

                {

                        fprintf(stderr, "Socket Error:%s\n\a ",strerror(errno));

                        exit(1);

                }

                strncpy(ifr.ifr_name, ETH_NAME, IFNAMSIZ);
                ifr.ifr_name[IFNAMSIZ - 1] = 0;

      if (ioctl(sock1, SIOCGIFADDR, &ifr) < 0)//获取本机主机ip
                        {
            perror("ioctl";
            return;
                 }

      memcpy(&saddr, &ifr.ifr_addr, sizeof(saddr));//保存到saddr中

           setsockopt(sock1,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));//set socket option

           setuid(getpid());//no choice,only superuser can use raw socket

           while(1){
                                pthread_mutex_lock(&time_mutex);
                                sleep(wait_to_resendtime();
                                pthread_mutex_unlock(&time_mutex);

                                pthread_mutex_lock(&send_mutex);

                                serial_sending(sock1,&saddr,&daddr,1,300);
                                pthread_mutex_unlock(&send_mutex);
               }


}  


void send_tcp(int sockfd,struct sockaddr_in *saddr,struct sockaddr_in *daddr,int priority)

{//发送优先级为priority的包,saddr保存本机ip,daadr保存目的主机ip


                char buffer[BUFSIZE];     //for reserving our data packet

                struct iphdr *ip;

                struct tcphdr *tcp;

                int buf_len;
                int rdm_data,rdm_wait;



                buf_len=sizeof(struct iphdr)+sizeof(struct tcphdr)+randBytes(1000);

                memset(buffer,'A',buf_len);


                ip=(struct iphdr*)buffer;

                ip->version=IPVERSION;           //version occupied 4 bits generally

                ip->ihl=sizeof(struct ip)>> 2;   //length of head of IP packet

                ip->tos=priority;                       //type of service

                ip->tot_len=htons(BUFSIZE);      //length of IP packet

                ip->id=0;                        //let system fill out this

                ip->frag_off=0;                  //same to above, let's save some time               

                ip->ttl=MAXTTL;                  //the longest time 255

                ip->protocol=IPPROTO_TCP;        //it is TCP that we want to send  

                ip->check=0;                     //let system check sum **/

                ip->daddr=daddr->sin_addr.s_addr; // the object that we want to assault



                tcp= (struct tcphdr*)(buffer + sizeof(struct iphdr));

                tcp->source= htons(LOCALPORT);     //source port

                tcp->dest= daddr->sin_port;       //destination port

                tcp->seq= random();               //TCP packet sequence

                tcp->ack_seq= 0;                  //TCP packet ack sequence

                tcp->doff= 5;                     //TCP packet data offset

                tcp->syn= 1;                      //I want to establish a connection

                tcp->check= 0;                    //TCP header checksum       


                ip->saddr=saddr->sin_addr.s_addr;//source ip address

      tcp->check=check_sum((unsigned short*)tcp, sizeof(struct tcphdr));  

      sendto(sockfd,buffer,buf_len,0,(struct sockaddr*)daddr,sizeof(struct sockaddr_in));

}





unsigned short check_sum(unsigned short *addr,int len)

{//校验和

                register int nleft=len;

                register int  sum=0;

                register short *w=addr;

                short answer=0;



                while(nleft>1)

                {

                                sum+=*w++;

                                nleft-=2;

                }

                if(nleft==1)

                {

                                *(unsigned char*)(&answer)=*(unsigned char*)w;

                                sum+=answer;

                }

   

                sum=(sum>> 16)+(sum&0xffff);

                sum+=(sum>> 16);

                answer=~sum;

                return(answer);

}


void thread_create(void)
{
        int temp;
        memset(&thread, 0, sizeof(thread));  //initializing

                    /*创建线程*/
        if((temp = pthread_create(&thread[0], NULL, packet_sender_0, NULL)) != 0)  //comment2
                printf("creating packet_sender_0 failure!\n";
        else
                printf("creating packet_sender_0 successful!\n";

        if((temp = pthread_create(&thread[1], NULL, packet_sender_1, NULL)) != 0)  //comment3
                printf("creating packet_sender_1 failure!\n";
        else
                printf("creating packet_sender_1 successful!\n";

}

void thread_wait(void)
{
                                /*等待线程结束*/
                        if(thread[0] !=0) {   
                pthread_join(thread[0],NULL);
                printf("thread packet_sender_0 has finished!\n";
                        }

                        if(thread[1] !=0) {   
                pthread_join(thread[1],NULL);
                printf("thread packet_sender_1 has finished!\n");
                        }
}


int main()
{
                pthread_mutex_init(&send_mutex,NULL);
                pthread_mutex_init(&time_mutex,NULL);

                printf("main program creating......\n");
      thread_create();
      printf("main program is waiting for finishing......\n");
      thread_wait();

                return 0;
}

错误显示为:
main program creating......
creating packet_sender_0 successful!
creating packet_sender_1 successful!
main program is waiting for finishing......
Socket Error:Operation not permitted


这个程序只是想模拟一下网络数据包的随机性效果,去掉一个线程源码就能发包成功,在另一头机器上就可以得到,只是开2个线程时就出错了。望高手相助。

论坛徽章:
0
2 [报告]
发表于 2011-09-11 03:24 |只看该作者
小人的位置实际上是‘)’右括号

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
3 [报告]
发表于 2011-09-11 09:40 |只看该作者
[quote]小人的位置实际上是‘)’右括号
[size=2][color=#999999]ljbphoebe 发表于 2011-09-11 03:24[/color] [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=21445866&ptid=3594028][img]http://bbs.chinaunix.net/images/common/back.gif[/img][/url][/size][/quote]


    代碼用[code] [/code]括起來。

论坛徽章:
0
4 [报告]
发表于 2011-09-13 12:44 |只看该作者
同步 异步问题

论坛徽章:
0
5 [报告]
发表于 2011-09-28 11:47 |只看该作者
不知有结果没
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP