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); //关闭连接
}

 

posted @ 2015-07-02 18:12  leezhxing  阅读(252)  评论(0编辑  收藏  举报