套接口socket编程(Client/Server编程实例) - Go语言中文社区

套接口socket编程(Client/Server编程实例)


基本概念                                                                                                                                         

套接口也就是网络中的ID。网络通信,归根到底还是进程间通信(不同计算机上的进程间的通信)。在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址。

  • IP地址:在网络中唯一标识一台主机,32
  • 端口号:在主机中唯一标识一个进程,16
  • IP+port:在网络环境中唯一标识一个进程(socket)

      socket也称套接字,是linux文件的一种类型(伪文件:不占存储空间的文件。linux 有7中文件, 1.普通文件  2.目录(d)3.字符设备文件(c) 4.块设备文件(b) 5.套接口文件(s)[如我们开启MySQL服务后,在/var/lib/mysql/下生成的mysql.sock文件,关闭MySQL服务后,这个文件就消失了],6.管道(p):有两端,读端 r:流出 fd[0]     写段w:流入 fd[1]         7.符号链接文件(l)[有点儿像WIN下的快捷方式]  其中占存储的有三种:普通,目录,软链接)

       socket成对出现,

       一个文件描述符指向两个缓冲区,一个读一个写。

预备知识                                                                                                                                          、

网路字节序:

       TCP/IP规定,网路数据流应采用大端字节序,即低地址高字节。(大端:低地址--高位   高地址--地位    小端:低--低 高--高,即端口号和IP地址都是以网路字节序存储的,网络字节序使用的是大端模式。称给某个系统所采用的字节序为主机字节序,它可能是小端模式也可能是大端模式。

       为使网络编程具有可移植性,使同样的C代码在大端和小端计算机上编译后能正常运行,可以调用一下库函数做网络字节序和主机字节序的转换。

#include<arpa/inet.h>
uint32_t  htoal(uint32_t hostlong);
uint16_t  htons(uint16_t hostshort);
//返回的是网络字节序
uint32_t ntoh1(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
//返回的主机字节序
//h表示host,to,n代表network,s代表short,l表示long
//端口16位 ,ip 32位

 套接口的数据结构                                                                                                                                

      在Linux中,每一种协议都有自己的网络地址数据结构,以sockaddr_开头,如IPV4对应的是sockaddr_in.

           //man 7 ip 查看

           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */
            /*套接口结构地址族,如IPV4为AF_INET*/
               in_port_t      sin_port;   /* port in network byte order */
            /*16位TCP或UDP端口号,网络字节顺序*/
               struct in_addr sin_addr;   /* internet address */
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };

C/S编程                                                                                                                                                  

服务器是指在网络上提供服务的应用程序,客户机是指用户为了得到某种服务所需要 运行的应用程序,即申请服务的程序。一个服务器程序可以同时接收多个客户机的请求。

 

server.c:
socket() 建立套接字
bind()  绑定IP 端口号(struct sockaddr_in addr 初始化)
listen() 指定最大同时发起连接数
accept()  阻塞等待客户端发起连接
read()
小--大
write 给客户端
close();

 

client.c:
socket();
bind();可以依赖“隐式绑定”,即写不写都行
connect();发起连接
write();
read();
close();
 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<sys/socket.h>
 4 #include<stdlib.h>
 5 #include<arpa/inet.h>
 6 #include<ctype.h>
 7 #include<strings.h>
 8 #define SERV_PORT 6666 //端口号
 9 int main(void)
10 {
11    int lfd,cfd;//定义套接口描述符
12    struct sockaddr_in serv_addr;//定义服务器IPV4套接口地址数据结构serv_addr
13    struct sockaddr_in clie_addr;//d定义客户端client
14    socklen_t clie_addr_len;
15    char buf[BUFSIZ],clie_IP[BUFSIZ];//用BUFSIZ就不需要自己定义宏了
16    int i,n;
17    lfd=socket(AF_INET,SOCK_STREAM,0);//AF_INET:IPV4 AF_INET6:IPV6
18    bzero(&serv_addr,sizeof(serv_addr));//清0,memset清任何数 
19    serv_addr.sin_family=AF_INET;//设置addr的成员信息
20    serv_addr.sin_port=htons(SERV_PORT);//本地字节序转换为网络字节序
21    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);//IP地址设为本地IP INADDR_ANY本地任意IP
22 
23    bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));//绑定端口
24 
25    listen(lfd,128);//最多可以接受128个客户端的请求,监听ifd描述符
26 
27    clie_addr_len=sizeof(clie_addr);
28    cfd=accept(lfd,(struct sockaddr *)&clie_addr,&clie_addr_len);//bind accept connect 需要强转
29    printf("client IP:%s,client port:%dn",inet_ntop(AF_INET,&clie_addr.sin_addr,clie_IP,sizeof(clie_IP)),ntohs(clie_addr.sin_port));
30    while(1){
31    n= read(cfd,buf,sizeof(buf));
32    for(i=0;i<n;i++)
33    {
34      buf[i]=toupper(buf[i]);//下写转换为大写
35    }
36    write(cfd,buf,n);
37    }
38    close(lfd);
39    close(cfd);
40 
41    return 0;
42 
43 }
server.c
 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<sys/socket.h>
 4 #include<stdlib.h>
 5 #include<arpa/inet.h>
 6 #include<ctype.h>
 7 #include<string.h>
 8 #define SERV_PORT 6666
 9 #define SERV_IP "127.0.0.1 "
10 int main(void)
11 {
12     int cfd;
13     int n;
14     char buf[BUFSIZ];
15     struct sockaddr_in serv_addr;
16    // socklen_t serv_addr_len;
17     cfd = socket(AF_INET,SOCK_STREAM,0);
18     memset(&serv_addr,0,sizeof(serv_addr));
19     serv_addr.sin_family=AF_INET;//设置addr的成员信息
20     serv_addr.sin_port=htons(SERV_PORT);//本地字节序转换为网络字节序
21     inet_pton(AF_INET,SERV_IP,&serv_addr.sin_addr.s_addr);
22  //    serv_addr.sin_addr=*((struct in_addr *)host->haddr);
23     connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));//客户端程序发起连接请求
24    while(1)
25    {
26    fgets(buf,sizeof(buf),stdin);//hello world ----fgets---"hello worldn"从键盘写 
27    write(cfd,buf,strlen(buf));
28    n=read(cfd,buf,sizeof(buf));
29    write(STDOUT_FILENO,buf,n);
30    }
31    close(cfd);
32    return 0;
33 }
client.c

 

版权声明:本文来源博客园,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.cnblogs.com/wy9264/p/10478353.html
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-11-10 10:02:45
  • 阅读 ( 911 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢