关闭

linux C ----- udp, tcp, unix socket通信简单例子

标签: socketunixtcpudp
3421人阅读 评论(0) 收藏 举报
分类:

udp socket

相关知识

UDP的程序设计可以分成客户端和服务器端两个部分。两者的主要差别在于对地址的绑定函数,客户端可以不用进行地质和端口的绑定。(客户端是随机拿一个大于1024的端口去连接的)
和TCP相比,UDP缺少connect(),listen(),accept()函数 【因为tcp面向连接,而UDP是无连接的。】
服务端的UDP编程:

动作 函数
创建 socket()
绑定 bind()
发送 sendto()
接收 recvfrom()
关闭 close()

客户端和服务端相比没有绑定bind()的步骤。

服务端的recvfrom是阻塞的,直到接收到数据。
关键词:数据包套接字,套接字文件描述符。

socket常见的套接字类型:
- AF_INET(又称 PF_INET)是IPv4网络协议的套接字类型
- AF_INET6 是IPv6网络协议的套接字类型
- AF_UNIX 属于Unix系统本地通信

socket常见的套接字选项:

SOCK_STREAM SOCK_DGRAM
数据流 数据包
有保障 无保障
面向连接 面向无连接
TCP/IP UDP
    int s=socket(AF_INET,SOCK_DGRAM,0);
    if(s==-1){
        perror("create socket: ");
        return -1;
    }
    struct sockaddr serv;
    serv.sin_family=AF_INET;   
    serv.sin_addr.s_addr=htol(INADDR_ANY);  // 任意本地IP,网络字节序
    serv.sin_port=htos(PORT);  //网络字节序
    bind(s,(struct sockaddr*)&serv,sizeof(serv));  //绑定套接字和地址

解释“绑定套接字和地址”,实质上是指明发送数据的IP和端口。

截图来自: http://blog.csdn.net/xiongping_/article/details/47722049
这里写图片描述
关于sockaddr和sockaddr_in的区别:
http://blog.csdn.net/joeblackzqq/article/details/8258693
它们的联系:
这里写图片描述

udp socket 例子

编写一个程序,使用udp通信,client是10.21.1.142, server是10.21.1.229,port是3000. client发送end能使得程序结束。
客户端:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 3000

int main(){ 
        int s=socket(AF_INET,SOCK_DGRAM,0);
        if(s==-1){
             perror("create socket error: ");
             exit(1);
        }
        struct sockaddr_in serv;
        bzero(&serv,sizeof(serv));
        serv.sin_family=AF_INET;   
        serv.sin_addr.s_addr = inet_addr("10.21.1.229");    //htonl(INADDR_ANY); 
        serv.sin_port=htons(PORT);
        char buff[105];
        int ret;
        while(1){
             ret=read(STDIN_FILENO,buff,105);
             if(ret==-1){
                  perror("read error: ");
                  break;
             }
             buff[ret]=0;
             sendto(s,buff,strlen(buff),0,(struct sockaddr *)&serv,sizeof(serv));
             if(strcmp(buff,"end\n")==0){
                  printf("client process end.\n");
                  break;
             }
             int addr_len=sizeof(serv);
             if((ret=recvfrom(s,buff,105,0,(struct sockaddr *)&serv,&addr_len))==-1){
                  perror("recvform error: ");
                  break;
             }
             buff[ret]=0;
             printf("receive message from server: %s",buff);
        }
        close(s);
        return 0;
}

服务端:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 3000

int main(){ 
    int s=socket(AF_INET,SOCK_DGRAM,0);
        if(s==-1){
        perror("create socket error: ");
        exit(1);
    }
    struct sockaddr_in serv,client;
    bzero(&serv,sizeof(serv));
    serv.sin_family=AF_INET;   
    serv.sin_addr.s_addr=inet_addr("10.21.1.229");//htol(INADDR_ANY); 
    serv.sin_port=htons(PORT);  //网络字节序
    if(bind(s,(struct sockaddr*)&serv,sizeof(serv))==-1){//绑定套接字和地址
        perror("bind error: ");
        exit(1);
    }
    while(1){
        char buff[105];
        int addr_len=sizeof(client);
        int ret=recvfrom(s,buff,105,0,(struct sockaddr *)&client,&addr_len); // once success, we get client.
        if(ret==-1){
            perror("recvfrom error: ");
            break;
        }
        buff[ret]=0;
        if(strcmp(buff,"end\n")==0){
            printf("server process end.\n");
            break;
        }
        printf("receive message from client: %s",buff);
            ret=read(STDIN_FILENO,buff,sizeof(buff));
        if(ret<0){
            perror("read error: ");
            break;
        }
        if(sendto(s,buff,ret,0,(struct sockaddr *)&client,addr_len)==-1){
            perror("sendto error: ");
            break;
        }
    }
    close(s);
    return 0;
}

会话:

$ ./udp1 
hello, I'm client
receive message from server: I'm server, I got message.
oh, congratulation.
receive message from server: hahaha
end
client process end.
$ ./udp1 
receive message from client: hello, I'm client
I'm server, I got message.
receive message from client: oh, congratulation.
hahaha
server process end.

tcp socket

相关知识

通用的套接字地址

struct sockaddr
{
unsigned short int sa_family;
char sa_data[14];
};

用户和内核进行数据交互:
得到数据: recv(), accept()
传入数据: send(), bind()
表示地址长度的参数在得到数据的函数中是传地址的, 而在传入数据的函数则是传值的. (对比accept和bind就知道这是正确的.)
tcp server and client work as:
这里写图片描述

tcp socket 例子

编写tcp socket通信例子, 分为客户端和服务端部分,当客户端发送”end”时,结束程序.
tcp_server.c:

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

const int port = 3000;
const int MAX = 10; /* biggest number of connected clients */
const char IP[] = "192.168.123.4";

int main(){
    int server_fd=socket(AF_INET,SOCK_STREAM,0);
    if(server_fd == -1){
        perror("socket: ");
        return -1;
    }
    struct sockaddr_in server;
    bzero(&server,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_addr.s_addr=htonl(INADDR_ANY); //inet_addr(IP);   /*  both ways are ok. */
    server.sin_port=htons(port);
    if(bind(server_fd,(struct sockaddr *)&server,sizeof(server))==-1){
        perror("bind: ");
        return -1;
    }
    if(listen(server_fd,MAX) == -1){
        perror("listen: ");
        return -1;
    }

    struct sockaddr_in client;
    int client_len=sizeof(client);
    int conn = accept(server_fd, (struct sockaddr *)&client, &client_len); 
    if(conn == -1){
        perror("accept: ");
        return -1;
    }
    char buff[105];
    while(1){
        memset(buff,0,sizeof(buff));
        if(read(conn,buff,sizeof(buff)) == -1){
            perror("read: ");
            break;
        }
        if(strcmp(buff,"end\n") == 0){
            puts("the server process end. ");
            break;
        }
        printf("recv message from client: %s", buff);
        memset(buff,0,sizeof(buff));
        if(read(STDIN_FILENO,buff,sizeof(buff)) == -1){
            perror("read: ");
            break;
        }
        if(write(conn,buff,strlen(buff)) == -1){
            perror("send: ");
            break;
        }
    }
    close(conn);
    close(server_fd);
    return 0;
}

tcp_client.c:

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

const int port = 3000;
const int MAX = 10; /* biggest number of client_fdected clients */
const char IP[] = "192.168.123.4";

int main(){
    int client_fd=socket(AF_INET,SOCK_STREAM,0);
    if(client_fd == -1){
        perror("socket: ");
        return -1;
    }
    struct sockaddr_in server;
    bzero(&server,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_addr.s_addr=inet_addr(IP);
    server.sin_port=htons(port);
    if(connect(client_fd,(struct sockaddr *)&server,sizeof(server))==-1){
        perror("client_fdect: ");
        return -1;
    }
    char sends[105],recvs[105];
    while(1){
        read(STDIN_FILENO,sends,sizeof(sends));
        if(send(client_fd,sends,strlen(sends),0)==-1){
            perror("send: ");
            break;
        }
        if(strcmp(sends,"end\n") == 0){
            puts("the client end.");
            break;
        }
        memset(recvs,0,sizeof(recvs));
        if(read(client_fd,recvs,sizeof(recvs))==-1){
            perror("recv: ");
            break;
        }
        printf("recv message from server: %s",recvs);
        memset(sends,0,sizeof(sends));
    }
    close(client_fd);
    return 0;
}

会话:

./tcps
recv message from client: hello
I got your message.
recv message from client: ok, every thins seems good.
client, we works.
the server process end.

./tcpc
hello
recv message from server: I got your message.
ok, every thins seems good.
recv message from server: client, we works.
end
the client end.

Unix socket

相关知识

Unix域协议族用于同一台主机上客户机、服务器通信。
Unix域中两种类型的套接字:字节流套接字(类似于tcp)、数据包套接字(类似于udp)。
Unix域套接字的传输速度是tcp的两倍。
Unix域套接字和传统套接字相比,他是用路径名来表示协议族的描述。
Unix域地质结构:

#define UNIX_PATH_MAX   108
struct sockaddr_un {
    __kernel_sa_family_t sun_family; /* AF_UNIX */
    char sun_path[UNIX_PATH_MAX];   /* pathname */
};

sun_family: AF_UNIX (known as AF_LOCAL)
sun_path: 必须是绝对路径,文件默认访问权限是0777

unix socket例子

一个客户端和服务器通信(本地)的例子. 当客户端发送end时,结束会话.
un_sock_serv.c:

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

const char path[]="/tmp/server";
int main(){
    int server_fd,client_fd;
    struct sockaddr_un server_addr, client_addr;
    unlink(path);
    server_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if(server_fd == -1){
        perror("socket: ");
        exit(1);
    }
    server_addr.sun_family=AF_UNIX;
    strcpy(server_addr.sun_path,path);
    if(bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1){
        perror("bind: ");
        exit(1);
    }
    listen(server_fd,10);  //server listen most 10 requests.
    puts("server is listening: ");
    int client_len=sizeof(client_addr);
    client_fd=accept(server_fd,(struct sockaddr *)&client_addr,(int *)&client_len);
    if(client_fd == -1){
        perror("accept: ");
        exit(1);
    }
    char recv[105], send[105];
    int i;
    while(1){
        memset(recv,0,sizeof(recv));
        if(read(client_fd,recv,105)==-1){
            perror("read: ");
            break;
        }
        if(strcmp(recv,"end\n")==0){
            printf("the server process end.\n");
            break;
        }
        printf("recv message from client: %s",recv);
        memset(send,0,sizeof(send));
        if(read(STDIN_FILENO,send,sizeof(send))==-1){
            perror("read: ");
            break;
        }
        if(write(client_fd,send,strlen(send))==-1){
            perror("write: ");
            break;
        }
    }
    close(server_fd);
    unlink(path);
}

un_sock_client.c:

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

const char path[]="/tmp/server";
int main(){
    int server_fd,client_fd;
    struct sockaddr_un server_addr, client_addr;
    //unlink(path);
    server_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if(server_fd == -1){
        perror("socket: ");
        exit(1);
    }
    server_addr.sun_family=AF_UNIX;
    strcpy(server_addr.sun_path,path);
    if(connect(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) == -1){
        perror("connect: ");
        exit(1);
    }
    char recv[105],send[105];
    int i;
    puts("the client started, please enter your message: ");
    while(1){
        memset(send,0,sizeof(send));
        if(read(STDIN_FILENO,send,105)==-1){
            perror("read: ");
            break;
        }
        if(write(server_fd,send,strlen(send))==-1){
            perror("send: ");
            break;
        }
        if(strcmp(send,"end\n")==0){
            printf("the client process end.\n");
            break;
        }
        memset(recv,0,sizeof(recv));
        if(read(server_fd,recv,105)==-1){
            perror("recv: ");
            break;
        }
        printf("recv message from server: %s",recv);
    }
    close(server_fd);
    unlink(path);
    return 0;
}

会话:

$ ./exes
server is listening: 
recv message from client: hello, I'm client
I'm server, I get your message.
recv message from client: ok, it seems goods.
yeah, it works.
the server process is end.

$ ./exec
the client started, please enter your message: 
hello, I'm client
recv message from server: I'm server, I get your message.
ok, it seems goods.
recv message from server: yeah, it works.
end
the client process end.
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Linux的SOCKET编程详解

Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统。由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 UNIX BSD有:管道(pipe)、命名管道...
  • hguisu
  • hguisu
  • 2012-04-10 17:44
  • 249079

unix环境高级编程-------socket(套接字)

一、socket是什么?      socket就是用来通信的,本博客所讲的socket是基于tcp/ip协议的(当然还可以采用其他不同的网络协议来通信)?首先我们来了解一下tcp/ip协议:      首先记住,每台电脑在网络中都有一个i...
  • chenxun2009
  • chenxun2009
  • 2015-10-30 00:10
  • 2370

linux下unix socket通信--基于udp

#include #include #include #include #include #include #include #include #include #include #define MSG_ADDR_A    ...
  • zhongcaogen
  • zhongcaogen
  • 2016-04-28 10:11
  • 198

使用psql命令基于udp(unix-domain-socket)协议连接postgresql数据库

netstat命令用法参考链接:https://linux.cn/article-2434-1.htmlhttps://segmentfault.com/a/1190000008633528关于UDP与TCP的关系:http://blog.csdn.net/li_ning_/article/deta...
  • pg_hgdb
  • pg_hgdb
  • 2017-11-27 10:39
  • 110

网络编程学习笔记一:Socket编程

“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket。 ——有感于实际编程和开源项目研究。 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你...
  • gneveek
  • gneveek
  • 2013-03-21 01:11
  • 122026

linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数

一、UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX ...
  • Simba888888
  • Simba888888
  • 2013-06-12 16:19
  • 11476

嵌入式 Unix-domain-socket详解UDP

int video_stream_net_func_udp(void) { #if 0         int server_sockfd;          ...
  • skdkjxy
  • skdkjxy
  • 2013-12-24 23:32
  • 922

UNIX网络编程——UDP编程模型

使用UDP编写的一些常见得应用程序有:DNS(域名系统),NFS(网络文件系统)和SNMP(简单网络管理协议)。     客户不与服务器建立连接,而是只管使用sendto函数给服务器发送数据报,其中必须指定目的地(即服务器)的地址作为参数。类似的,服务器不接受来自客户的...
  • ctthunagchneg
  • ctthunagchneg
  • 2013-07-25 12:16
  • 1620

UNIX Socket UDP 代码

客户端 #include #include #include #include #include #include #include #include // UDP 通讯程序代码-Client int main(int argc, char* argv[]) { if (a...
  • wzq9706
  • wzq9706
  • 2011-10-30 20:27
  • 1632

UNIX域套接字及TCP、UDP示例

UNIX域套接字用于在同一台机器上运行的进程之间的通信。虽然因特网域套接字可用于同一目的,但UNIX域套接字的效率更高。UNIX域套接字仅仅复制数据;它们并不执行协议处理,不需要添加或删除网络报头,无需计算检验和,不要产生顺序号,无需发送确认报文。 1.非命名的UNIX域套接字 UNIX套接...
  • bytxl
  • bytxl
  • 2015-08-22 18:08
  • 2813
    个人资料
    • 访问:331303次
    • 积分:8856
    • 等级:
    • 排名:第2517名
    • 原创:575篇
    • 转载:13篇
    • 译文:0篇
    • 评论:36条
    我的链接
    最新评论