《网络编程》-第1章 – 理解网络编程和套接字

第1章 – 理解网络编程和套接字

套接字( socket ):是网络数据传输用的软件设备,用来连接该网络。

1、服务器创建过程:

第一步:调用 socket 函数创建套接字。

第二步:调用 bind 函数分配IP地址和端口号。

第三步:调用 listen 函数转为可接收请求状态。

第四步:调用 accept 函数受理连接请求。

socket() 函数

#include <sys/socket.h>

int  socket ( int domain, int type, int protocol );

功能:

​ 创建套接字。(套接字是网络数据传输用的软件设备)

参数:

​ domain:一般写 AF_INET

​ type:类型,一般写 SOCK_STREAM

​ protocol:一般写 0

返回值:

​ 成功时返回文件描述符,失败返回 -1

【注】sockaddr_in 结构体

一般用 sockaddr_in 来表示bind() 里面的参数sockaddr

struct  sockaddr_in {
	short  int  sin_family;                /* 协议族,在socket编程中只能是AF_INET */
    unsigned  short  int  sin_port;       /* 端口号 */
	struct  in_addr  sin_addr;            /* IP地址 */
	unsigned  char  sin_zero[8];          /* Same size as struct sockaddr */
};

struct  in_addr {
	unsigned  long  s_addr;
};

bind() 函数

#include <sys/types.h>          
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

功能:

​ 给创建好的套接字分配IP地址和端口号。

参数:

​ sockfd:文件描述符,为socket()生成

​ addr :sockaddr_in结构体型变量,因为addr是结构体指针,所以实参要用&。

​ addrlen:结构体变量长度

返回值:

​ 成功返回 0, 失败返回-1

eg. struct sockaddr_in serv_addr;

​ serv_sock = socket(PF_INET, SOCK_STREAM, 0);

​ bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)

listen() 函数

#include <sys/socket.h>

int listen( int sockfd, int backlog );

功能:

​ 把套接字转化成可接受连接的状态。

参数:

​ sockfd:套接字文件描述符

​ vacklog:连接队列的最大长度 eg. 5

返回值:

​ 成功返回0, 失败返回 -1

accept() 函数

#include <sys/socket.h>

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

功能:

​ 接受连接请求。

参数:

​ sockfd:套接字文件描述符

​ addr:sockaddr_in结构体型变量 (此时定义的结构体变量用于客户端,bind()用于服务器)

​ addrlen:结构体变量长度

返回值:

​ 成功返回文件描述符,失败返回 -1

2、客户端创建过程

第一步:调用 socket 函数创建套接字

第二步:调用 connect 函数向服务器端发送连接请求

connect() 函数

#include <sys/socket.h>

int connect( int cockfd, struct sockaddr *serv_addr, soc klen_t addrlen );

功能:

​ 在客户端调用客户端套接字。

参数:

​ sockfd:套接字文件描述符

​ addr:sockaddr_in结构体型变量

​ addrlen:结构体变量长度

返回值:

​ 成功返回0, 失败返回-1

3、Linux文件操作

文件描述符

在这里插入图片描述

这三个是系统固定的,所以自己创建文件的文件描述符一般是从3开始。

open() 函数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);

功能:

​ 打开文件以读写数据

参数:

​ pathname:文件名的字符串地址(一般用相对地址)

​ flags 类似于给的权限位

在这里插入图片描述

返回值:

​ -1 表示失败

​ 正常情况下会返回文件描述符( >0 )

close() 函数

#include <unistd.h>

int close(int fd);

功能:

​ 关闭文件

参数

​ fd:需要关闭的文件或套接字的文件描述符。

返回值:

​ 成功返回0, 失败返回-1。

write() 函数

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

功能:

​ 将数据写入文件。

参数:

​ fd:文件描述符

​ buf:要传输数据的缓冲地址值

​ count:缓冲区大小。

返回值:

​ 成功 返回写入的字节数; 失败返回-1

read() 函数

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

功能:

​ 读取文件中的数据

参数:

​ fd:文件描述符

​ buf:要传输数据的缓冲地址值

​ count:缓冲区大小。

返回值:

​ 成功 返回接收的字节数;失败返回-1

4、课后习题

1) 套接字在网络编程中的作用是什么?为什么称它为套接字? P2

网络编程就是编写程序让两台联网的计算机相互交换数据。在我们不需要考虑物理连接的情况下,我们只需要考虑如何编写传输软件。操作系统提供了名为“套接字”,套接字是网络传输用的软件设备。

socket英文原意是插座:我们把插头插到插座上就能从电网获得电力供给,同样,为了与远程计算机进行数据传输,需要连接到Internet,而编程中的“套接字”就是用来连接该网络的工具。

2) 在服务器端创建套接字后,会依次调用listen函数和accept函数。请比较并说明两者作用?

listen:将套接字转为可接受连接方式。

accept:受理连接请求,并且在没有连接请求的情况调用该函数,不会返回。直到有连接请求为止。二者存在逻辑上的先后关系

3) Linux中,对套接字数据进行I/O时可以直接使用I/O相关函数;而在Windows中则不可以。原因为何?

Linux把套接字也看作是文件,所以可以用文件I/O相关函数;而Windows要区分套接字和文件,所以设置了特殊的函数

4) 创建套接字后一般会给它分配地址,为什么?为了完成地址分配需要调用哪些函数?

要在网络上区分来自不同机器的套接字,所以需要地址信息。分配地址是通过bind()函数分配IP地址和端口号。

5) Linux中的文件描述符与Windows的句柄实际上非常类似。请以套接字为对象说明他们的含义?

Linux的文件描述符是为了区分指定文件而赋予文件的整数值(相当于编号)。Windows的文件描述符其实也是套接字的整数值,其目的也是区分指定套接字。

6) 底层文件I/O函数与ANSI标准定义的文件I/O函数之间有何区别?

ANSI标准定义的输入、输出函数是与操作系统(内核)无关的以C标准写成的函数。相反,底层文件I/O函数是直接提供的。理论上ANSI标准I/O提供了某些机制,性能上由于底层I/O

代码入口

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值