网络通讯

面向连接的网络应用程序分为客户端与劳务器端。服务器端的实践流程一般也4步,客户端程序相对简便易行,一般需要少单步骤。

UDP

服务器端执行流程4步如下:

UDP多播

  1. 多播(组播)的概念
      多播,也号称“组播”,将网络被千篇一律业务系列主机举行了逻辑上的分组,举办数量收发的上该数额才以同分组中展开,其他的主机没有在者分组不可能收发对应的数额。
      在广域网上播放的时光,其中的交流机和路由器只为内需获取数据的主机复制并转账数。主机可以向路由器请求加入或者退某个组,网络中之路由器和互换机发接纳地复制并传输数据,将数据仅传输给组内的主机。多播的这种效能,能够一样潮将数据发送至大半独主机,又可以担保不影响其余非待(未参预组)的主机的外通
    信。

  2. 多播的亮点
    周旋于人情的分外的单播,多播具有如下的长处:

  • 享有同种业务的主机插手同一数据流,共享同一通道,节省了带富和服务器的优点,具有广播的长处而而从未广播所欲的带来富。
  • 服务器的总带宽不为客户端带宽的范围。由于组播协议由接收者的需求来确定是否开展数据流的转速,所以服务器端的拉动富是常量,与客户端的数据无关。
  • 与单播一样,多播是容在广域网即Internet上拓展传输的,而广播就在同等局域网上才会开展。
  1. 多播的毛病
  • 多播与单播相比较没有纠错机制,当有误的时难以弥补,可是足以当以层来贯彻此种力量。
  • 多播的大网帮忙是缺点,需要路由器和网络协议栈的支撑。
  • 多播的施用紧要出网上视频、网上会等。

(1)调用socket函数,建立一个效接字,该套接字用于接下去的大网通信。

(2)调用bind函数,将该套接字绑定到一个地点,并创立一个端口号,

(3)调用listen函数,使用该套接字监听连接要

(4)当求来到时,调用accept函数复制该套接字处理要

客户端执行流程2步如下:

(1)调用socket函数,创造一个模仿接字

(2)调用connect函数使用该套接字与服务器举办连接

劳器端和客户端程序的家喻户晓区别在于客户端程序不欲调用bind函数,bind函数的用意是将拟接字绑定一个IP地址和端口号,因为霎时片只要素得以于网环境被唯一地址表示一个历程。假若套接字没有用bind函数绑定地址与端口,那么调用listen函数和connect函数的时光内核会自动为仿效接字绑定。因而可知,假使没动bind函数,调用listen函数和connect函数的时内核会自动为仿照接字绑定。看起好像bind函数是剩下的,但实情并无是这么。

大家先来看望listen函数和connect是怎么绑定套接字的,connect函数绑定套接字之时光使用的是一个装置好的地址结构(sockaddr_in)作为参数,结构被指定了服务器的地址与要通信的捧口号。可是listen函数没有是参数,多以listen函数不能使安装好的地方结构,只好出于网装置IP地址与端口号。也就是说在劳务器端,假使无动bind函数的口舌,创制套接字时利用的凡如今系面临空闲端口的套接字。

这样的话,服务器端的次第不爱戴客户端的IP地址,也即使即对应的捧口号是根本临时叫的一个端口,是即兴的,每一回执行服务器程序的下,使用的依旧例外之端口。不过以客户端是要指定通信的服务器的端口的,若是非应用bind函数,每一回的端口是随便的语句,那么每一遍重启服务程序之后都使对准客户端的次举办调,那样做不仅未创建,而且工作量相当挺,因而于服务器端bind函数效用大重大。

下边是一个施用bind函数的劳务器端程序,可以作为参照通晓。

图片 1

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAX_LINE 100

int main(void)
{
       struct sockaddr_in sin;
       struct sockaddr_in cin;
       int l_fd;
       int c_fd;
       socklen_t len;
       char buf[MAX_LINE];
       char addr_p[INET_ADDRSTRLEN];
       int port = 8000;
       int n;
       bzero(&sin, sizeof(sin));
       sin.sin_family = AF_INET;
       sin.sin_addr.s_addr = INADDR_ANY;
       sin.sin_port = htons(port);
       /*创立套接字,使用TCP协议*/
       if((l_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
       {
              perror("fail to creat socket");
              exit(1);
       }
       /*将地址和套节字绑定*/
       if(bind(l_fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
       {
              perror("fail to bind");
              exit(1);
       }
       /*开始监听连接请求*/
       if(listen(l_fd, 10) == -1)
       {
              perror("fail to listren");
              exit(1);
       }
       printf("waiting...\n");
       while(1)
       {
              /*接受连接请求,从此函数中返回后就可以开始通信了*/
              if((c_fd = accept(l_fd, (struct sockaddr *) &cin, &len)) == -1)
              {
                     perror("fail to accept");
                     exit(1);
              }
              /*调用recv函数读取客户端传来的信息,不设置任何特殊的标志*/
              n = recv(c_fd, buf, MAX_LINE, 0);
             if(n = -1)
              {
                     perror("fail to receive");
                     exit(1);
              }
              else if(n == 0)
              {
                     printf("the connect has been closed\n ");
                     close(c_fd);
                     continue;
              }
              /*将客户端地址转换为字符串*/
              inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));
              printf("client IP is %s, port is %s \n", addr_p, ntohs(cin.sin_port));
              printf("connect is : %s\n", buf);
              n = strlen(buf);
              sprintf(buf, "%d", n);
              /*使用send函数将转换后的字符串发送给客户端,不设置任何特殊的标志*/
              n = send(c_fd, buf, strlen(buf) + 1, 0);
              if(n == -1)
              {
                     perror("fail to send");
                     exit(1);
              }
              if(cloes(c_fd) == -1)
              {
                     perror("fail to close");
                     exit(1);
              }
       }
       return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图