免费注册 查看新帖 |

Chinaunix

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

求救!!:关于UNIX系统UDP编程问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-10-26 10:25 |只看该作者 |倒序浏览
现在领导让我做一个在SGI IRIX操作系统下,用C语言编写一个接收来自于WINDOWS操作系统的UDP协议下的报文,并存在内存的某个地址下。由于从来没有接触过UNIX操作系统和网络编程,真是无从下手呀,哪为好心的大虾能指点一二呀,如果能有个例子程序最好了。实在着急呀!!哪位高手能帮助我,真是不胜感激呀!!
跟贴给我或发E-MAIL:  mhf_mhf2000@yahoo.com.cn

论坛徽章:
0
2 [报告]
发表于 2005-10-26 11:19 |只看该作者

求救!!:关于UNIX系统UDP编程问题

服务器端:

#include<sys/socket.h>;
#include<string.h>;
#include<netinet/in.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<fcntl.h>;
#include<sys/stat.h>;
#include<unistd.h>;
#include<errno.h>;
#include<sys/select.h>;
#include<sys/time.h>;
#include<unistd.h>;
#include<sys/types.h>;

#define SERV_PORT 2500
#define MAX_SIZE 1024*40

void recvUDP(char name[20],int sockfd)
{
int ret,fd;
mode_t fdmode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
char mesg[MAX_SIZE];
fd_set rdset;
struct timeval tv;
int rlen,wlen;
int i;

fd = open(name,O_RDWR|O_CREAT|O_APPEND,fdmode);
if(fd == -1)
{
printf("open file %s error:%n",name,strerror(errno));
exit(-1);
}

for(i=0;;i++)
{
tv.tv_sec = 1;
tv.tv_usec = 0;

FD_ZERO(&rdset);
FD_SET(sockfd,&rdset);

ret = select(sockfd+1,&rdset,NULL,NULL,&tv);
if(ret == -1)
{
printf("select error %s\n",strerror(errno));
exit(-1);
}
else if(ret==0)
{
printf("select timeout,continue circle\n";
continue;
}

if(FD_ISSET(sockfd,&rdset))
{
memset(mesg,0,MAX_SIZE);
rlen = read(sockfd,mesg,MAX_SIZE);
if(rlen <=0 )
{
printf("read error %s\n",strerror(errno));
exit(-1);
}

if(!strcmp(mesg,"end")
{
printf("recv end.\n";
break;
}

wlen = write(fd,mesg,rlen);
if(wlen != rlen )
{
printf("write error %s\n",strerror(errno));
exit(-1);
}
}

printf("The %d times write\n",i);
}

close(fd);
}

int main(int argc, char *argv[])
{
int sockfd;
int r;
struct sockaddr_in servaddr;

sockfd = socket(AF_INET,SOCK_DGRAM,0); /*create a socket*/

/*init servaddr*/
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);

/*bind address and port to socket*/
if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1)
{
perror("bind error";
exit(-1);
}

r = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);

recvUDP(argv[1],sockfd);

return 0;

}


客户端:
#include<sys/types.h>;
#include<sys/socket.h>;
#include<string.h>;
#include<netinet/in.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<arpa/inet.h>;
#include<fcntl.h>;
#include<sys/stat.h>;
#include<errno.h>;
#include<sys/sysinfo.h>;
#include<sys/select.h>;
#include<sys/time.h>;
#include<unistd.h>;

#define MAX_SIZE 1024*40
#define SERV_PORT 2500


void connectUDP(char name[20],int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
{
char buf[MAX_SIZE];
fd_set wrset;
struct timeval tv;
int rlen,wlen;
int fd;
int ret;
int i;

if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
{
perror("connet error";
exit(1);
}
else
printf("connect server ok!\n";

fd = open(name,O_RDONLY);
if(fd==-1)
{
printf("fopen error %s\n",strerror(errno));
exit(-1);
}

i=0;

while(1)
{
tv.tv_sec = 1;
tv.tv_usec = 0;

FD_ZERO(&wrset);
FD_SET(sockfd,&wrset);

ret = select(sockfd+1,NULL,&wrset,NULL,&tv);
if(ret == -1)
{
printf("select error %s\n",strerror(errno));
exit(-1);
}
else if(ret==0)
{
printf("select timeout,continue circle\n";
continue;
}

memset(buf,0,MAX_SIZE);
if(FD_ISSET(sockfd,&wrset))
{
rlen = read(fd,buf,MAX_SIZE);
if(rlen <0)
{
printf("fread data error %s\n",strerror(errno));
exit(-1);
}
else if(rlen==0)
{
wlen = write(sockfd,"end",3);
if(wlen !=3)
{
printf("write end error\n",strerror(errno));
exit(-1);
}

printf("all complete\n";

close(fd);
close(sockfd);
exit(0);
}

wlen = write(sockfd,buf,rlen);
if(wlen != rlen)
{
printf("write data to sockfd error:%s\n",strerror(errno));
exit(-1);
}

i++;

usleep(500);
printf("The %d times read\n",i);
}
}
}


int main(int argc ,char *argv[])
{
char *fh;
struct sysinfo s_info;
float time1,time2;
int error1,error2;
int sockfd;
struct stat fsize;
struct sockaddr_in servaddr;
error1= sysinfo(&s_info);
time1 = s_info.uptime;
int r;

if(argc != 3)
{
printf("useage:udpclient<IPaddress>;\n";
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_port = htons(SERV_PORT);

if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0)
{
printf("[%s]is not a valid IPaddress\n",argv[1]);
exit(1);
}
fh = argv[2];

sockfd =socket(AF_INET,SOCK_DGRAM,0);

r = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);

connectUDP(argv[2],sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
fprintf(stderr,"ServerIP:\t%s\n",argv[1]);
if(stat(argv[2],&fsize) == -1)
perror("failed to get fiel statusi\n";
else
fprintf(stderr,"file name:\t%s\nfile size:\t%dK\n",argv[2],fsize.st_size/1024);
error2=sysinfo(&s_info);
time2 = s_info.uptime;
printf("tranfice file time =%fs\n",(time2-time1));
}


Makefile
all:send recv

send:send.c
gcc -Wall send.c -o send
recv:recv.c
gcc -Wall recv.c -o recv

clean:
rm -rf send recv

论坛徽章:
0
3 [报告]
发表于 2005-10-26 11:57 |只看该作者

求救!!:关于UNIX系统UDP编程问题

非常感谢!!
另外我在问一个比较EASY的问题
您在程序中设端口号是2500 ,我看有的程序设8888或1500,不知UDP通信的端口号是固定的还是根据不同的机器端口号不同呢?我的机器是SGI工作站,操作系统是IRIX,我如何知道它UDP服务端口号呢?

论坛徽章:
0
4 [报告]
发表于 2005-10-26 12:00 |只看该作者

求救!!:关于UNIX系统UDP编程问题

UDP端口可以是大于1024 的所有未用端口。
nmap -sU <IP>;

论坛徽章:
0
5 [报告]
发表于 2005-10-26 12:06 |只看该作者

求救!!:关于UNIX系统UDP编程问题

非常感谢!!能否再问一个问题?
因为我的目的是得到WINDOWS操作系统得来的数据,我的UNIX端接收程序只要查询端口有没有报文发过来就可以了,与交互是什么操作系统没什么关系吧?谢谢!
还有就是,我在这个网站上down了个程序,
/*           服务端程序  server.c           */
#include <stdlib.h>;
#include <stdio.h>;
#include <errno.h>;
#include <string.h>;
#include <unistd.h>;
#include <netdb.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <sys/types.h>;
#include <arpa/inet.h>;
#define SERVER_PORT     8888
#define MAX_MSG_SIZE    1024

void udps_respon(int sockfd)
{
       struct sockaddr_in addr;
       int    n;
               socklen_t addrlen;
       char    msg[MAX_MSG_SIZE];
        
       while(1)
       {       /* 从网络上读,写到网络上面去   */
                               memset(msg, 0, sizeof(msg));
                               addrlen = sizeof(struct sockaddr);
                               n=recvfrom(sockfd,msg,MAX_MSG_SIZE,0,
                       (struct sockaddr*)&addr,&addrlen);
               /* 显示服务端已经收到了信息  */
               fprintf(stdout,"I have received %s",msg);
               sendto(sockfd,msg,n,0,(struct sockaddr*)&addr,addrlen);
       }
}

int main(void)
{
       int sockfd;
       struct sockaddr_in      addr;
        
       sockfd=socket(AF_INET,SOCK_DGRAM,0);
       if(sockfd<0)
       {
               fprintf(stderr,"Socket Error:%s\n",strerror(errno));
               exit(1);
       }
       bzero(&addr,sizeof(struct sockaddr_in));
       addr.sin_family=AF_INET;
       addr.sin_addr.s_addr=htonl(INADDR_ANY);
       addr.sin_port=htons(SERVER_PORT);
       if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0)
       {
               fprintf(stderr,"Bind Error:%s\n",strerror(errno));
               exit(1);
       }
       udps_respon(sockfd);
       close(sockfd);
}
-------------------------------------------------------------------------------/*          客户端程序             */
#include <stdlib.h>;
#include <stdio.h>;
#include <errno.h>;
#include <string.h>;
#include <unistd.h>;
#include <netdb.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <sys/types.h>;
#include <arpa/inet.h>;
#define MAX_BUF_SIZE    1024

void udpc_requ(int sockfd,const struct sockaddr_in *addr,socklen_t len)
{
       char buffer[MAX_BUF_SIZE];
       int n;
       while(fgets(buffer,MAX_BUF_SIZE,stdin))         
       {        /*   从键盘读入,写到服务端   */
               sendto(sockfd,buffer,strlen(buffer),0,addr,len);
               bzero(buffer,MAX_BUF_SIZE);

               /*   从网络上读,写到屏幕上    */
                               memset(buffer, 0, sizeof(buffer));
               n=recvfrom(sockfd,buffer,MAX_BUF_SIZE, 0, NULL, NULL);
               if(n <= 0)
                               {
                                       fprintf(stderr, "Recv Error %s\n", strerror(errno));
                                       return;
                               }
                               buffer[n]=0;
               fprintf(stderr, "get %s", buffer);
       }
}


int main(int argc,char **argv)
{
       int sockfd,port;
       struct sockaddr_in      addr;
        
       if(argc!=3)
       {
               fprintf(stderr,"Usage:%s server_ip server_port\n",argv[0]);
               exit(1);
       }
        
       if((port=atoi(argv[2]))<0)
       {
               fprintf(stderr,"Usage:%s server_ip server_port\n",argv[0]);
               exit(1);
       }
        
       sockfd=socket(AF_INET,SOCK_DGRAM,0);
       if(sockfd<0)
       {
               fprintf(stderr,"Socket  Error:%s\n",strerror(errno));
               exit(1);
       }      
       /*      填充服务端的资料      */
       bzero(&addr,sizeof(struct sockaddr_in));
       addr.sin_family=AF_INET;
       addr.sin_port=htons(port);
       if(inet_aton(argv[1],&addr.sin_addr)<0)
       {
               fprintf(stderr,"Ip error:%s\n",strerror(errno));
               exit(1);
       }
                if(connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1)
               {
                       fprintf(stderr, "connect error %s\n", strerror(errno));
                       exit(1);
               }
       udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in));
       close(sockfd);
}
在sgi 工作站的irix系统上程序编译都通过了,但先运行
server.exe后再运行cilent.exe 127.0.0.1 8888 后输入字符串后,服务器端没有反应。这是为什么呢?

论坛徽章:
0
6 [报告]
发表于 2005-10-26 12:35 |只看该作者

求救!!:关于UNIX系统UDP编程问题

你把客户端代码的下面几行修改成如下格式:
void udpc_requ(int sockfd,const struct sockaddr *addr,socklen_t len)

udpc_requ(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in));

论坛徽章:
0
7 [报告]
发表于 2005-10-26 13:10 |只看该作者

求救!!:关于UNIX系统UDP编程问题

好的,我去试试!非常非常非常感谢!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

论坛徽章:
0
8 [报告]
发表于 2005-10-26 13:22 |只看该作者

求救!!:关于UNIX系统UDP编程问题

刚才我的修改只是改正了系统编译时的报错信息,
我用 red hat 9.0 编译通过并且运行正常。
楼主用的是什么系统?编译器?
#./recv &
#./send 127.0.0.1 8888
asd
I have received asd
get asd
da
I have received da
get da
das
I have received das
get das
dsa
I have received dsa
get dsa
das
I have received das
get das
das
I have received das
get das
das
I have received das
get das

论坛徽章:
0
9 [报告]
发表于 2005-10-26 15:30 |只看该作者

求救!!:关于UNIX系统UDP编程问题

刚试过了,还是不行呀。
我的操作系统是irix 2.8 ,C的编译器我也不清楚,网管今天培训去了,没有问到。说是irix自带的C的编译器。呜呜!!我这边编译过没有出错信息。
编译方法是
cc -c cilent.c
cc -o cilent.exe cilent.o
cc -c server.c
cc -o server.exe server.o
然后分别在两个窗口运行的server.exe
cilent.exe 127.0.0.1 8888
然后敲了一些字符,没有反应了.......
能否看出我操作是否妥当?
网管明天回来,如果不行,明天问了他再告诉你!
很麻烦你,谢谢!!!!

论坛徽章:
0
10 [报告]
发表于 2005-10-26 15:43 |只看该作者

求救!!:关于UNIX系统UDP编程问题

你把 server.exe &
client.exe 127.0.0.1 8888
看看
或者开2个终端:一个 run server :run client
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP