面向连接的网络应用程序分为客户端和服务器端。服务器端的执行流程一般为4步,客户端程序相对简单,一般需要两个步骤。

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

(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函数的服务器端程序,可以作为参考理解。

#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;
}

网络通讯中 bind函数的作用的更多相关文章

  1. javascript中bind函数的作用

    javascript的bind的作用 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  2. bind函数的作用

    面向连接的网络应用程序分为客户端和服务器端.服务器端的执行流程一般为4步,客户端程序相对简单,一般需要两个步骤. 服务器端执行流程4步如下: (1)调用socket函数,建立一个套接字,该套接字用于接 ...

  3. 在网络通讯中应用Protobuf

    在网络通讯中应用Protobuf Protobuf的设计非常适用于在网络通讯中的数据载体,它序列化出来的数据量少再加上以K-V的方式来存储数据,对消息的版本兼容性非常强:还有一个比较大的优点就是有着很 ...

  4. php中session_start()函数的作用

    php中session_start()函数的作用 用$_SESION之前必须要session_start()----其中之一的功能,$_SESSION是服务器端的cookie,相当一个大数组(浏览器关 ...

  5. C++中虚函数的作用和虚函数的工作原理

    1 C++中虚函数的作用和多态 虚函数: 实现类的多态性 关键字:虚函数:虚函数的作用:多态性:多态公有继承:动态联编 C++中的虚函数的作用主要是实现了多态的机制.基类定义虚函数,子类可以重写该函数 ...

  6. 网络编程api bind函数细节 select 细节

    struct sockaddr_in bindaddr; bindaddr.sin_family = AF_INET; bindaddr.sin_addr.s_addr = htonl(INADDR_ ...

  7. C++中虚函数的作用浅析

    虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...

  8. C++中虚函数的作用是什么?它应该怎么用呢?(转)

    虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...

  9. C++中虚函数的作用

    一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Po ...

随机推荐

  1. springboot项目用maven打jar包

    clean package -Dmaven.test.skip=true idea eclipse STS

  2. week9:Recommender Systems

    Collaborative  filtering 的原理不是很理解? xi   是每一步电影的特征向量,表示浪漫/动作

  3. 两个事务 update同一张表出现的死锁问题 (转载)

    引言 近来做省一级计算机一级考试系统的时候,学生端进行大批量判分的时候,出现了这样的问题(事务(进程 ID 262)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品.请重新运行该事务.): 这 ...

  4. Linux内存管理-高端内存(一)

    高端内存是指物理地址大于 896M 的内存.对于这样的内存,无法在“内核直接映射空间”进行映射. 为什么? 因为“内核直接映射空间”最多只能从 3G 到 4G,只能直接映射 1G 物理内存,对于大于 ...

  5. 在CentOS上安装node.js的时候报错:No acceptable C compiler found!解决办法

    在CentOS上安装node.js的时候报错:No acceptable C compiler found! 原因:没有c编译器. 解决办法:安装GCC 命令如下: #yum install gcc ...

  6. Java中的类与对象

    一.类与对象的概念 1.类:类是一组相同属性.方法的对象的集合:对象是类的具体化. 2.对象具有类所有的特征,类拥有的,对象就拥有. 3.类与对象他们的关系是相对的. 类有什么特点 1) 类是对象的类 ...

  7. docker启动mysql

    docker启动mysql docker run -p 3306:3306 -v /dockermysqlcfg/config/my.cnf:/etc/mysql/my.cnf -v /dockerm ...

  8. docker故障问题修复

    systemctl start docker启动 systemctl restart docker重启 执行 vi /etc/sysconfig/selinux , 把 selinux 属性值改为di ...

  9. 修复 Cydia 不能上网的问题

    使用 h3lix 越狱 10.3.3 的 iPhone5,进入 Cydia 不能联网解决方法:打开 Cydia,进入已安装列表,点击 Cydia Installer 卸载,然后看到桌面上就没有 Cyd ...

  10. HTML5 -- 浏览器数据缓存 -- indexedDB

    IndexedDB是一种可以让你在用户的浏览器内持久化存储数据的方法,为web应用提供了丰富的查询功能,使我们的应用在在线和离线都能正常工作. 由于 IndexedDB 本身的规范还在持续演进中,当前 ...