udp通信
示例参考网上的一篇博客,
21天学通linux c的示例有些地方有错误
还有一些地方让人很迷糊
这个例子很好,敲一遍就都理解了
注释部分要详细的看看
//client端 #include <stdio.h> #include <stdlib.h> /* exit() 需要 */ #include <unistd.h> #include <strings.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT 4567 #define MAXDATASIZE 100 int main(int argc, const char *argv[]) { int fd; //socket产生的文件描述符
int numbytes; //接收recvfrom()获取的字节长度
char recvbuf[MAXDATASIZE]; char sendbuf[MAXDATASIZE]; struct hostent *he; //获取域名对应的ip struct sockaddr_in server,client; //本机连接示例:./udp_client.out 127.0.0.1
//就是gethostbyname()的参数是IP那也是可以的。 if (argc !=2) { printf("Usage: %s %s \n",argv[0], "www.163.com"); exit(1); } //如果传入的是域名,通过域名解析出IP if ((he=gethostbyname(argv[1]))==NULL){ printf("gethostbyname() error\n"); exit(1); } //创建socket if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1){ printf("socket() error\n"); exit(1); } //构建套接字:protocol + port + ip bzero(&server,sizeof(server)); //等同于memset server.sin_family = AF_INET; server.sin_port = htons(PORT); //转换端口为网络字符顺序 server.sin_addr = *((struct in_addr *)he->h_addr); //he->h_addr是IP地址,因为是字符串,所以是指针,所以用(struct in_addr *)转为in_addr结构体指针,然后用*在转为结构体
//上边如果要写IP地址的话,server.sin_addr.s_addr = inet_addr("127.0.0.1");
//开始写成了server.sin_addr.s_addr = htonl(inet_addr("127.0.0.1"))报错了,注意和server端的代码区别。
//inet_addr()返回的地址已经是网络字节格式,所以你无需再调用 函数htonl()。
//发送和接收消息,发送和接收的sockaddr都是server端的 socklen_t len; len=sizeof(struct sockaddr_in); while (1) { printf("input message:"); fgets(sendbuf,40,stdin); //得到stdin信息 //发送 sendto(fd,sendbuf,strlen(sendbuf),0,(struct sockaddr *)&server,len); //接收,注意接收时sockaddr的长度是指针 if ((numbytes=recvfrom(fd,recvbuf,MAXDATASIZE,0,(struct sockaddr *)&server,&len)) == -1){ printf("recvfrom() error\n"); exit(1); } recvbuf[numbytes]='\0'; printf("Server Return Reverse Message: %s\n",recvbuf); } close(fd); //关闭 }
//server端 #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 4567 #define MAXDATASIZE 100 main() { int sockfd; //socket产生的文件描述符 struct sockaddr_in server; struct sockaddr_in client; socklen_t sin_size; int num; char recvmsg[MAXDATASIZE]; char sendmsg[MAXDATASIZE]; char condition[] = "quit"; //关闭连接的条件 //创建socket if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { /* handle exception */ perror("Creating socket failed."); exit(1); } //构建server端sockaddr_in,用于bind() bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); //主机字符顺序转换为网络字符顺序 server.sin_addr.s_addr = htonl (INADDR_ANY); //主机字符顺序转换为网络字符顺序,ip为INADDR_ANY //bind if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { /* handle exception */ perror("Bind error."); exit(1); } /** * 与服务端建立连接后系统把远程主机的信息保存在client。 * server端的接收和发送的sockaddr都是client * 在使用client前无需对其设置 * 并且像下边可以直接用client.sin_addr等信息 */ sin_size=sizeof(struct sockaddr_in); while (1) { //接收 num = recvfrom(sockfd,recvmsg,MAXDATASIZE,0,(struct sockaddr *)&client,&sin_size); if (num < 0){ perror("recvfrom error\n"); exit(1); } recvmsg[num] = '\0'; //注意这个技巧的使用 printf("You got a message (%s) from %s\n",recvmsg,inet_ntoa(client.sin_addr) ); /* 10进制转字符串IP */ if(strcmp(recvmsg,condition)==0) break; int i=0; for(i = 0 ; i < num ; i ++) { sendmsg[i] = recvmsg[num-1-i]; //反转字符串,这个技巧也可以注意 } sendmsg[num]='\0'; //这个和上边一样的技巧 sendto(sockfd,sendmsg,strlen(sendmsg),0,(struct sockaddr *)&client,sin_size); } close(sockfd); //关闭连接 }