一.概念介绍

  网络程序分为服务端程序和客户端程序。服务端即提供服务的一方,客户端为请求服务的一方。但实际情况是有些程序的客户端、服务器端角色不是这么明显,即互为Linux培训

客户端和服务端。

  我们编写网络程序时,一般是基于TCP协议或者UDP协议进行网络通信的。兄弟连Linux培训小编整理:

  TCP:(Transfer Control Protocol)传输控制协议是一种面向连接的协议,当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端之间的传输是可靠的。

  UDP:(User DatagramProtocol)用户数据报协议是一种非面向连接的协议, 这种协议并不能保证我们的网络程序的连接是可靠的。

  我们编写的网络程序具体采用哪一类协议,要视具体情况而定。比如,如果是大数据量的通信,而且对数据的完整性要求不是特别高,则可以采用UDP协议,以得到更快的传输速率。如果我们是要实现一些诸如文件传输、社交通讯之类的功能,就需要采用TCP协议通信,以保证传输的可靠性。

  二.初等网络函数介绍

  nt socket(int domain, inttype,int protocol)

  domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等).

  AF_UNIX只能够用于单一的Unix 系统进程间通信,

  而AF_INET是针对Internet的,因而可以允许在远程

  主机之间通信(当我们 man socket时发现 domain可选项是 PF_*而不是AF_*,因为glibc是posix的实现所以用PF代替了AF,

  不过我们都可以使用的).

  type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)

  SOCK_STREAM表明我们用的是TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流.

  SOCK_DGRAM 表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.

  protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了 socket为网络通讯做基本的准备.

  成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况.

  int bind(int sockfd, structsockaddr *my_addr, int addrlen)

  sockfd:是由socket调用返回的文件描述符.

  addrlen:是sockaddr结构的长度.

  my_addr:是一个指向sockaddr的指针. 在中有sockaddr的定义

  struct sockaddr{

  unisgned short as_family;

  char sa_data[14];

  };

  不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替.在中有sockaddr_in的定义

  struct sockaddr_in{

  unsigned short sin_family;

  unsigned short intsin_port;

  struct in_addr sin_addr;

  unsigned char sin_zero[8];

  }

  我们主要使用Internet所以

  sin_family一般为AF_INET,

  sin_addr设置为INADDR_ANY表示可以和任何的主机通信,

  sin_port是我们要监听的端口号.sin_zero[8]是用来填充的.

  bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样

  int listen(int sockfd,intbacklog)

  sockfd:是bind后的文件描述符.

  backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度.

  listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.

  int accept(int sockfd,struct sockaddr *addr,int *addrlen)

  sockfd:是listen后的文件描述符.

  addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen和accept是服务器端用的函数,

  accept调用时,服务器端的程序会一直阻塞到有一个 客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符,

  这个时候服务器端可以向该描述符写信息了. 失败时返回-1

  int connect(int sockfd,struct sockaddr * serv_addr,int addrlen)

  sockfd:socket返回的文件描述符.

  serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址

  addrlen:serv_addr的长度

  connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符 失败时返回-1.

  更多函数请查看man …….

  int getaddrinfo(const char*node, const char *service,

  const struct addrinfo*hints,

  struct addrinfo **res);

  三.初等网络函数使用实例

  一个教科书式的服务器端程序流程为:

  建立套接字socket()--->将套接字绑定到ip地址bind()----->建立监听套接字listen()------>开始等待客户端请求accpet()

  详细代码如下:

  复制代码代码如下:

  #include <stdlib.h>

  #include <stdio.h>

  #include <errno.h>

  #include <string.h>

  #include <unistd.h>

  #include<sys/socket.h>

  #include<netinet/in.h>

  #include<sys/types.h>

  #include <netdb.h>

  int main(int argc, char*argv[])

  {

  int sockfd,connfd;

  struct sockaddr_in srvaddr;

  struct sockaddr_in cliaddr;

  int len,port;

  charhello[]="Hi,welcome to linux-code!\n";

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){

  fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));

  exit(1);

  }

  /* 服务器端填充 sockaddr结构 */

  bzero(&srvaddr,sizeof(structsockaddr_in));

  srvaddr.sin_family=AF_INET;

  srvaddr.sin_addr.s_addr=htonl(INADDR_ANY);

  srvaddr.sin_port=htons(1113);

  /* 捆绑sockfd描述符 */

  if(bind(sockfd,(structsockaddr *)(&srvaddr),sizeof(struct sockaddr))==-1){

  fprintf(stderr,"Binderror:%s\n\a",strerror(errno));

  exit(1);

  }

  /* 监听sockfd描述符 */

  if(listen(sockfd,5)==-1){

  fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));

  exit(1);

  }

  len=sizeof(structsockaddr_in);

  while(1){ /* 服务器阻塞,直到客户程序建立连接 */

  if((connfd=accept(sockfd,(structsockaddr *)(&cliaddr),&len))==-1){

  fprintf(stderr,"Accepterror:%s\n\a",strerror(errno));

  exit(1);

  }

  fprintf(stderr,"Serverget connection from %s\n",inet_ntoa(cliaddr.sin_addr));

  if(write(connfd,hello,strlen(hello))==-1){

  fprintf(stderr,"WriteError:%s\n",strerror(errno));

  exit(1);

  }

  /* 这个通讯已经结束 */

  close(connfd);

  /* 循环下一个 */

  }

  close(sockfd);

  exit(0);

  }

  一个教科书式的客户端程序流程为:

  建立套接字socket()--->与服务器建立连接connect()

  详细代码如下:

  复制代码代码如下:

  #include <stdlib.h>

  #include <stdio.h>

  #include <errno.h>

  #include <string.h>

  #include <unistd.h>

  #include<sys/socket.h>

  #include<netinet/in.h>

  #include <sys/types.h>

  #include <netdb.h>

  int main(int argc, char*argv[]) {

  int sockfd; char buf[1024];

  struct sockaddr_in srvaddr;

  struct hostent *phost; intnbytes;

  if(argc!=3){

  fprintf(stderr,"Usage:%s<IP> <portnumber>\a\n",argv[0]);

  exit(1);

  }

  /* 客户程序开始建立 sockfd描述符 */

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){

  fprintf(stderr,"socketError:%s\a\n",strerror(errno));

  exit(1);

  }

  /* 客户程序填充服务端的资料 */

  bzero(&srvaddr,sizeof(srvaddr));

  srvaddr.sin_family=AF_INET;

  srvaddr.sin_port=htons(atoi(argv[2]));

  if (inet_pton(AF_INET,argv[1], &srvaddr.sin_addr) <= 0){

  fprintf(stderr,"inet_ptonError:%s\a\n",strerror(errno));

  exit(1);

  }

  /* 客户程序发起连接请求 */

  if(connect(sockfd,(structsockaddr *)(&srvaddr),sizeof(struct sockaddr))==-1){

  fprintf(stderr,"connectError:%s\a\n",strerror(errno));

  exit(1);

  }

  /* 连接成功了 */

  if((nbytes=read(sockfd,buf,1024))==-1){

  fprintf(stderr,"readError:%s\n",strerror(errno));

  exit(1);

  }

  buf[nbytes]='\0';

  printf("received data:%s\n",buf);

  /* 结束通讯 */

  close(sockfd);

  exit(0);

  }

  四.上述程序存在的问题

  先运行上述程序的服务端程序,再运行客户端程序,可以得到如下结果:

  服务器端结果:

  viidiot@ubuntu:~/code $./srv

  Server get connection from192.168.1.153

  Server get connection from127.0.0.1

  Server get connection from192.168.1.153

  客户器端结果:

  viidiot@ubuntu:~/code $./cli 192.168.1.153 1113

  received data:Hi,welcome tolinux-code!

  我们完成了一个简单的网络通信程序,该程序使用的io模型为同步(synchronous)阻塞(blocking)。服务器端调用accept(),write()等函数,如果没有客户端连接过来或者相应的文件描述符没有准备好写,程序就会在那里死死的等待,什么事情也不干。在实际应用中,这类程序是很少出现的。实际中使用的都是异步io模型。

Linux入门培训教程 linux网络编程socket介绍的更多相关文章

  1. Linux入门培训教程 linux下拷贝cp删除rm移动mv命令参数以及说明

    拷贝移动删除在windows中看起来这么简单,但linux经常使用的文字界面,所以对于linux系统 下拷贝cp删除 rm 移动mv命令参数就不得不需要了解和学习了 cp 该命令的功能是将给出的文件或 ...

  2. Linux入门培训教程 linux系统中文件I/O教程

    linux 文件I/O教程 一,文件描述符 对内核而言,所以打开的文件都通过文件描述符引用.每个进程都有一些与之关联的文件描述符.文件描述符是一个非负整数.当打开一个现有文件或创建一个新文件时,内核向 ...

  3. Java入门 - 高级教程 - 05.网络编程

    原文地址:http://www.work100.net/training/java-networking.html 更多教程:光束云 - 免费课程 网络编程 序号 文内章节 视频 1 概述 2 Soc ...

  4. 网络编程-Socket介绍

    Socket介绍 什么是socket?(5分钟) Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议 ...

  5. 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现

    一.客户端/服务器架构(C/S架构)                                                即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...

  6. Linux入门培训教程 常见linux命令释义

    快到中午吃饭了,然后忽然想起来samba里面没有添加用户.于是乎,就玩弄起了samba. Samba三下五除二就安装好了,想想window里面不断的点击下一步,还要小心提防各种隐藏再角落里的绑定软件. ...

  7. linux网络编程-socket(37)

    在编程的时候需要加上对应pthread开头的头文件,gcc编译的时候需要加了-lpthread选项 第三个参数是线程的入口参数,函数的参数是void*,返回值是void*,第四个参数传递给线程函数的参 ...

  8. Linux入门学习教程:虚拟机体验之KVM篇

    本文中可以学习到的命令: 1. aptitude 是apt-get 不会产生垃圾的版本 2.       dpkg -L virtualbox 显示属于该包的文件 lsmod | grep kvmfi ...

  9. Kail Linux渗透测试教程之网络扫描和嗅探工具Nmap

    Kail Linux渗透测试教程之网络扫描和嗅探工具Nmap 网络扫描和嗅探工具——Nmap Nmap也就网络映射器(Network Mapper),是一个免费开放的网络扫描和嗅探工具.该工具可以扫描 ...

随机推荐

  1. Shell编程、part3

    本节内容 1. shell流程控制 2. for语句 3. while语句 4. break和continue语句 5. case语句 6. shell编程高级实战 shell流程控制 流程控制是改变 ...

  2. 【LeetCode】714、买卖股票的最佳时机含手续费

    Best Time to Buy and Sell Stock with Transaction Fee 题目等级:Medium 题目描述: Your are given an array of in ...

  3. 跨域设置之corsheaders

    安装 pip install django-cors-headers 注册应用 INSTALLED_APPS = ( ... 'corsheaders', ... ) 中间层设置 MIDDLEWARE ...

  4. redhat java配置

    原来的java版本为1.4 whereis java后 将java原来的目录全部删除 拿来新的1.8的安装好的java包 vi /etc/profile插入 JAVA_HOME=/usr/local/ ...

  5. 第六次学习总结&&第四次实验总结

    Java实验报告 班级 1班 学号 20188390 姓名 宋志豪 实验四 类的继承 1.实验目的 (1)掌握类的继承方法: (2)变量的继承和覆盖,方法的继承.重载和覆盖实现: 2.实验内容 实验代 ...

  6. 15. AutoMapper 之映射继承(Mapping Inheritance)

    https://www.jianshu.com/p/e4f05403bd13 映射继承(Mapping Inheritance) 映射继承有两个功能: 从基类或接口配置继承映射配置 运行时多态映射 继 ...

  7. django Paginator 让分页变得完美

    参考大佬地址:https://www.zmrenwu.com/courses/django-blog-tutorial/materials/21/ 类视图 from django.contrib.au ...

  8. CentOs7 防火墙的开放与关闭及端口的设定

    1.查看firewall服务状态 systemctl status firewalld 2.查看firewall的状态 firewall-cmd --state 3.开启.重启.关闭.firewall ...

  9. 2019-11-29-WPF-轻量级-MVVM-框架入门-2.1.2

    title author date CreateTime categories WPF 轻量级 MVVM 框架入门 2.1.2 lindexi 2019-11-29 10:16:10 +0800 20 ...

  10. 在window环境下安装symfony2框架注意事项

    首先先放上放上安装的教程:http://www.symfonychina.com/doc/current/setup.html 然后说一下笔者遇到的坑 在运行这条命令的时候,虽然成功下载读取下来了,但 ...