linux上的socket通信(一)socket基础框架

一、c/s架构下的socket通讯框架图

 二、网络通信API

1.主机字节序&网络字节序

htonl

htons

ntohl

ntohs

2.socket地址

sockaddr_in

sockaddr_in6

3.ip地址转换函数

三、服务器端编程

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>

int main()
{
    //1.创建负责监听的套接字,命名为fd
    printf("1.create socket for listening\n");
    int fd=socket(AF_INET,SOCK_STREAM,0);//参数说明:1.ipv4类型 2.tcp->socket流 stream 3.default 0
    if(fd==-1){
        perror("socket error");
        return -1;
    }

    //2.套接字绑定本地的ip地址和端口号
    printf("2.binding local ip-port\n");
    struct sockaddr_in saddr;
    //initial saddr,使用sockaddr_in是为了方便输入输出
    saddr.sin_family=AF_INET;//与套接字的ipv4类型一致
    saddr.sin_port=htons(9999);//监听的本地端口号(注意需要从主机子节序转为网络子节序)
    saddr.sin_addr.s_addr=htonl(INADDR_ANY);//INADDR_ANY = 0,即表示地址为0.0.0.0,这个地址会自动对应到本地ip地址
    int ret=bind(fd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(ret==-1){
        perror("binding error");
        return -1;
    }

    //3.设置监听
    printf("3.set listen\n");
    ret=listen(fd,127);//参数说明:1.监听套接字fd 2.max num
    if(ret==-1){
        perror("listen error");
        return -1;
    }

    //4. 阻塞并等待连接
    printf("4. block and waiting for connection\n");
    struct sockaddr_in caddr;
    socklen_t addlen=sizeof(caddr);
    int cfd=accept(fd,(struct sockaddr*)&caddr,&addlen);//参数说明1.负责监听的套接字 2.接收到的客户端地址,因此创建了一个与客户端连接之后用于通讯的套接字cfd
    if(cfd==-1){
        perror("accept error\n");
        return -1;
    }

    //5.连接成功,打印客户端信息并进行通讯
    printf("5.connect successfully,print related infomation,then communicate with client\n");
    char ip[32];
    printf("client ip:%s,port:%d\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(caddr.sin_port));
    //ntohs net->host short
    while(1){
        //receive data
        char buff[1024];
        int len=recv(cfd,buff,sizeof(buff),0);
        if(len>0){
            printf("client say:%s\n",buff);
            send(cfd,buff,len,0);
        }
        else if(len==0){
            printf("client disconnect\n");
            break;
        }
        else{
            perror("receive error");
            break;
        }
    }
    //close file description
    close(fd);
    close(cfd);
    return 0;
}

四、客户端编程

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>

int main()
{
    //1. 创建通讯的套接字
    printf("1.create socket for communication\n");
    int fd=socket(AF_INET,SOCK_STREAM,0);//参数说明1.ipv4 2.tcp->socket stream 3.default 0
    if(fd==-1){
        perror("socket error");
        return -1;
    }

    //2.连接服务器的ip地址和端口号
    printf("2.connect server ip-port\n");
    struct sockaddr_in saddr;
    //initial saddr
    saddr.sin_family=AF_INET;//ipv4,same with fd
    saddr.sin_port=htons(9999);//服务器监听的端口号,注意要从主机字节序转为网络子字节序
    inet_pton(AF_INET,"172.16.116.5",&saddr.sin_addr.s_addr);//服务器的ip地址需要从主机字节序转为网络字节序
    int ret=connect(fd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(ret==-1){
        perror("connect error");
        return -1;
    }

    //3.与服务端通讯
    printf("3.communicate with client\n");
    int num=0;
    while(1){
     num++;
//send data char buff[1024];//data for send sprintf(buff,"hello world,%d...\n",num);//fill buffer send(fd,buff,strlen(buff)+1,0);//length=char-length+"\0" //receive data int len=recv(fd,buff,sizeof(buff),0);//block util receive data if(len>0){ printf("server say:%s\n",buff); } else if(len==0){ printf("server disconnect\n"); break; } else{ perror("receive error"); break; } sleep(1); } //close file description close(fd); return 0; }

五、调试验证

1.代码编写完毕保存成两个cpp文件:

 

 2.gcc进行编译:

 

 3.两个terminal开启服务端和客户端

(1)服务端

 

 (2)客户端

 

 

 

 

参考:ubuntu14.04中打开squid服务并将本机作为代理服务器

posted on 2021-09-14 18:53  freden  阅读(462)  评论(0编辑  收藏  举报