网络编程——TCP和UDP编程模型(TCP/UDP服务器和客户端-实现代码)

网络编程及其编程环境
通信连接:

局域网拓扑图:

广域网拓扑图:

编程环境:vim,linux,.....

TCP和UDP编程模型

1,传输层TCP和UDP
1)OSI七层模型


2)TCP协议 :传输控制协议,向用户进程提供可靠的全双工字节流
3)UDP协议:用户数据报协议,是一种无连接的协议,不可靠传输
2,TCP编程模型

1)客户端

2)服务器

例子1:socket()实现进程间通信,AF_UNIX
(1)服务器端;server.c

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
int main()
{
    int serverfd,clientfd;
    struct sockaddr_un server,client;
    int client_len=sizeof(client);
    //initial
    server.sun_family = AF_UNIX;
    strcpy(server.sun_path,"mysocketunix");
       
    //socket
    serverfd=socket(AF_UNIX,SOCK_STREAM,0);
    if(serverfd ==-1)
       {
       printf("create socket errror\n'");
       exit(1);
       }
    //bind
    if(bind(serverfd,(struct sockaddr *)&server,sizeof(server)) == -1)
    {
        printf("bind failure\n");
        close(serverfd);
        exit(1);
     }
     
    //listen
    if(listen(serverfd,20)==-1)
    {
        printf("listen error\n");
        close(serverfd);
        exit(1);
    }
    printf("listening.......\n");
    //accept
    clientfd=accept(serverfd,(struct sockaddr *)&client,&client_len);
    if(clientfd ==-1)
    {
    printf("accept error\n");
    close(serverfd);
    exit(1);
    }
    printf("accepted \n");
    //operation
    write(clientfd,"hello client !",14);
    printf("had writed to client\n");
    //close
    close(serverfd);
    close(clientfd);
return 0;
}

    

编译运行结果如下:

如图运行可执行文件后生成一个类似管道的文件mysocketunix

(1)客户端;client.c

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
int main()
{
    int clientfd;
    struct sockaddr_un client;
    char buf[100]={0};
    //initial
    client.sun_family = AF_UNIX;
    strcpy(client.sun_path,"mysockunix");
       
    //socket
    clientfd=socket(AF_UNIX,SOCK_STREAM,0);
    if(clientfd ==-1)
       {
       printf("create socket errror\n'");
       exit(1);
       }
    //connect
    if(connect(clientfd,(struct sockaddr *)&client,sizeof(client))==-1)
     {
        printf("connect error\n");
        exit(1);
     }
     
    //operation
    read(clientfd,buf,100);
    printf("get message : %s\n",buf);
    //close
    close(clientfd);
return 0;
}

运行服务器./ser; 然后客户端连接./cli;结果如下图:
<1>等待客户端的连接

<2>客户端成功连接

例子2:socket()实现网络通信,AF_INET
服务器: server.c

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<arpa/inet.h>


#define MAX_LISTEN 100

int main()
{       
        int server_fd,client_fd;
        struct sockaddr_in server,client;
        int client_len=sizeof(client);
        //initial socket object
        server.sin_family = AF_INET;
        server.sin_addr.s_addr =htonl(INADDR_ANY);
        server.sin_port =htons(8888);
        
        //socket
        server_fd=socket(AF_INET,SOCK_STREAM,0);
        if(server_fd == -1)
        {
        printf("socket error\n");
        exit(1);
        }
        //bind
        if(bind(server_fd,(struct sockaddr *)&server,sizeof(server))==-1)
        {
        printf("bind error\n");
        close(server_fd);
        exit(1);
        }
        
        //listen
        if(listen(server_fd,MAX_LISTEN)==-1)
        {
        printf("listen error\n");
        close(server_fd);
        exit(1);
        }
        printf("listening...........\n");
        //accept
        client_fd=accept(server_fd,(struct sockaddr *)&client,&client_len);
        if(client_fd==-1)
        {
        printf("accept error\n");
        close(server_fd);
        exit(1);
        }
        //operation write or send
        //write(client_fd,"hello client",12);
    send(client_fd,"hello client",12);
        //close
        close(client_fd);
        close(server_fd);
        
return 0;
}


客户端:client.c

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<arpa/inet.h>


int main()
{
        struct sockaddr_in client;
        int client_fd;
        char read_buf[128];
        //init 
        client.sin_family =AF_INET;
        client.sin_addr.s_addr =inet_addr("192.168.0.122");
        client.sin_port =htons(8888);
        
        //socket
        client_fd=socket(AF_INET,SOCK_STREAM,0);
        if(client_fd==-1)
        {
        printf("socket error\n");
        exit(1);
        }
        //connect
        if(connect(client_fd,(struct sockaddr*)&client,sizeof(client))==-1)
        {
        printf("connect error\n");
        close(client_fd);
        exit(1);
        }
        //operation read or recv
        //read(client_fd,read_buf,128);
    recv(client_fd,read_buf,128,0);
        printf("read_buf=%s\n",read_buf);
        //close
        close(client_fd);
return 0;
}

服务器server.c实现循环发送:

while(1)
{
//accept
        client_fd=accept(server_fd,(struct sockaddr *)&client,&client_len);
        if(client_fd==-1)
        {
        printf("accept error\n");
        close(server_fd);
        exit(1);
        }
        //operation write or send
        //write(client_fd,"hello client",12);
    send(client_fd,"hello client",12);
        //close
        close(client_fd);
}

客户端实现通过输入服务器主机名连接服务器,改进client.c内容如下:

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<arpa/inet.h>


int main(int argc,char *argv[])
{
        if(argc<2)
        {
        printf("please input two argment\n");
        exit(1);
        }
        
        struct hostent *myhost;
        struct sockaddr_in client;
        int client_fd;
        char read_buf[128];
        //init 
        client.sin_family =AF_INET;
        myhost = gethostbyname(argv[1]);
        if(!myhost)
        {
        printf("gethostname error\n");
        exit(1);
        }
        client.sin_addr = *((struct in_addr *)myhost->h_addr);//hostname to addr
        client.sin_port =htons(8888);
        
        //socket
        client_fd=socket(AF_INET,SOCK_STREAM,0);
        if(client_fd==-1)
        {
        printf("socket error\n");
        exit(1);
        }
        
        //connect
        if(connect(client_fd,(struct sockaddr*)&client,sizeof(client))==-1)
        {
        printf("connect error\n");
        close(client_fd);
        exit(1);
        }
        //operation
        //read(client_fd,read_buf,128);
        recv(client_fd,read_buf,128,0);
        printf("read_buf=%s\n",read_buf);
        //close
        close(client_fd);
return 0;
}



测试运行结果如下:

[注]不通过ip,而通过hostname来请求服务器;
有时候可能无法连接,是因为没有启动daytime服务,解决办法如下:
第一步:需要安装xinetd服务(其实daytime就包含在xinetd服务中)
第二部:修改/etc/xinetd.d/daytime文件.将此文件中的两个disable的值yes改为no.
第三步:注销一下系统或重启下xinetd服务
#/etc/init.d/xinetd restart
【注】字节转换函数(主机大端存储和网络小端存储之间的转换)

IP地址的转换函数

例子1:address convet to net和net convert to address

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
        struct in_addr my_addr;
        
        //convert address to network
        inet_aton("192.168.0.120",&my_addr);
        printf("address to network is:%d\n",my_addr.s_addr);
        
        printf("network to address is :%s\n",inet_ntoa(my_addr));
        
        return 0;
}

运行结果:

例子2;通过gethostbyname获取域名的主机IP

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main()
{
        struct in_addr my_addr;
        struct hostent *myhost;
        //get host address by DNS Name
        myhost = gethostbyname("www.baidu.com");
        my_addr.s_addr =(uint32_t)(myhost->h_addr);
        printf("www.baidu.com ip is : %s\n",inet_ntoa(my_addr));
        
        return 0;
}

运行结果:

3)通信过程三次握手四次握手分析

4)其他基本编程知识
网络字节序
套接字地址结构

值-结果 传递地址结构长度
<1>进程---->内核

<2>内核---->进程

IP地址转换的相关函数

5)拓展时间服务的功能--各个函数解析

socket()函数

connect()函数

bind()函数

listen()函数

accept()函数

3,UDP编程模型

recvfrom函数

sendto函数

服务器和客户端

1,UDP服务器
server.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <pthread.h>

int main(int argc,char *argv[])
{
    struct sockaddr_in server_ip,client_ip;
    socklen_t server_len,client_len;
    int sd;
    unsigned int rev;
    int err;
    char write_buf[128]={0},read_buf[128];
    
    sd=socket(AF_INET,SOCK_DGRAM,0);//创建一个套接字
    if(sd <0)
    {
        printf("create socket failure\n");
        return -1;
    }
    
    //初始化服务器IP及Port等
    bzero(&server_ip,sizeof(server_ip));//将对象清零,bzero比memset安全
    server_ip.sin_family =AF_INET;//ipv4的协议族
    server_ip.sin_port =htons(8888);//将主机数据转换为网络数据作为端口
    server_ip.sin_addr.s_addr =htonl(INADDR_ANY);//本地主机IP作为服务器地址
    memset(server_ip.sin_zero,0,8);//struct sockaddr_in的第三个参数

    //绑定本机为服务器
    err=bind(sd,(struct sockaddr*)&server_ip,sizeof(server_ip));
    if(err<0)
    {
        printf("bind error\n");
        close(sd);
        return -2;
    }
    printf("bind success\n");
        
    //获取客户端IP长度
    client_len=sizeof(client_ip);
    while(1)
    {
    //接收来自客户端的数据
     rev=recvfrom(sd,read_buf,sizeof(read_buf),0,(struct sockaddr*)&client_ip,&client_len);
    if(rev<0)
    {
        printf("recvform error\n");
        close(sd);
        return -3;
    }
    //打印客户端IP,端口Port及传过来的数据
    printf("rev_len=%d\n",rev);
    printf("client_ip=%s port=%d\n",inet_ntoa(client_ip.sin_addr),ntohs(client_ip.sin_port));
    printf("client says: %s\n",read_buf);
        //从标准输入向套接字读入数据
    fgets(write_buf,sizeof(write_buf),stdin);
    sendto(sd,write_buf,sizeof(write_buf),0,(struct sockaddr*)&client_ip,sizeof(client_ip));
    bzero(&client_ip,client_len);//清零操作
    bzero(write_buf,128);
    bzero(read_buf,128);
  }  
   close(sd);
return 0;
}

2,UDP客户端
client.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <pthread.h>


int main(int argc,char *argv[])
{
        int cd,rev;
        struct sockaddr_in server_ip,client_ip;
        socklen_t server_len,client_len;
        char read_buf[128]={0};
        char write_buf[128]={0};

        cd=socket(AF_INET,SOCK_DGRAM,0);
        if(cd<0)
        {
        printf("create socket failure\n");
        return -1;
        }
        
        //因为一开始客户端没有recvfrom,故不知道server的IP和端口,
    //这里需要自己初始化和绑定一次服务器的IP和端口
        server_ip.sin_family =AF_INET;//服务器协议族
        server_ip.sin_port =htons(8888);//服务器端口
        inet_pton(AF_INET,"192.168.0.120",&server_ip.sin_addr.s_addr);//服务IP
        memset(server_ip.sin_zero,0,8);//这行可以不写
        
        while(1)
        {
    //从标准输入读取数据到读缓存
        fgets(write_buf,128,stdin);
        //将读缓存里的数据写到套接字,发送给客户端
        sendto(cd,write_buf,sizeof(write_buf)+1,0,(struct sockaddr*)&server_ip,sizeof(server_ip));
        //读取服务器发过来的数据
        rev=recvfrom(cd,read_buf,sizeof(read_buf),0,NULL,NULL);
        if(rev<0)
        {
        printf("recvfrom error\n");
        close(cd);
        return -2;
        }
    //打印服务器的IP和端口以及数据
        printf("rev_len=%d\n",rev);
   printf("client_ip=%s port=%d\n",inet_ntoa(server_ip.sin_addr),ntohs(server_ip.sin_port));
        printf("server says : %s\n",read_buf);
        }
        close(cd);
        
        return 0;
}
发布了50 篇原创文章 · 获赞 13 · 访问量 1826

猜你喜欢

转载自blog.csdn.net/weixin_38251305/article/details/104046066