用SOCKET实现TCP通信
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二用SOCKET实现TCP通信
一、实验目的
熟练掌握 UDP、TCP Client/Server 模式的通信原理。
二、实验原理
1.socket编程相关知识
网络编程就是通过计算机网络与其他程序进行通信的程序, Socket 编程
是网络编程的主流工具。Socket API 是实现进程间通信的一种编程设施,也是一种为进程间提供底层抽象的机制。尽管应用开发人员很少需要在该层编写代码,但是理解 socket API 还是非常重要的。主要有两点原因:第一,高层设
施是构建于 socket API 之上的,它们是利用socket API 提供的操作来实现。第二,对于响应时间要求较高或运行于有限资源平台上的应用,甚至socket API 是唯一可用的进程间通信设施。
socket API 出现于 20 世纪 80 年代早期,作为 Berkeley Unix(BSD
4.2)操作系统程序库来通过进程间通信功能。现在主流操作系统都提供
socket API。在基于 Unix系统中,如 BSD、Linux 系统,socket API 是操作
系统内核的一部分;在 MS-DOS、Windows OS、 OS/2 等操作系统中, socket API 是以程序库形式提供的,如在 Windows系统中,socket API 被称为Winsock。Socket 接口规范可以适用多种通讯协议,主要是 TCP/IP。TCP/IP
是计算机互联最常适用的网络通讯协议,TCP/IP 的核心部分由网络操作系统的内核实现,应用程序通过编程接口来访问 TCP/IP,应用程序通讯的方式有图
36-1 所示。TCP/IP 使用一个网络地址和一个服务端口号来惟一地标识设备。
网络地址标识网络上的特定设备;端口号标识要连接到的该设备上的特定服务。网络通讯的基本模式如下:每一台通讯的主机都有一个本网络环境中惟一的 IP 地址,一台主机上往往有多个通讯程序存在,每个这样的程序都要占用一个通
讯端口。因此,一个 IP 地址,一个通讯端口,就能确定一个通讯程序的位置。
2. 基于C的Socket编程相关函数和数据类型
1.sockadd和sockaddr_in结构:
① sockaddr 结构
struct sockaddr
{
unsigned short sa_family; /*地址族,AF_xxx 有 IPV4 与 IPV6 等*/
char sa_data[14]; /*14 字节的协议地址*/
};
sa_family 一般为 AF_INET,表示 Internet 协议族,如是 AF_UNIX 表示
UNIX 协
议簇;sa_data 中包含该 socket 的 IP 地址和端口号。
② in_ add 结构,用来存储四字节的 IP 地址
struct in_addr{
unsigned long s_addr;
};
③ sockaddr_in 结构
struct sockaddr_in
{
short int sin_family; /*地址族*/
unsigned short int sin_port; /*端口号*/
struct in_add sin_addr; /*IP 地址*/
unsigned char sin_zero[8]; /*填充 0 以保持与 struct sockaddr 同样大小*/
};
该结构中 sin_zero 使得 sockaddr 和 sockaddr_in 指针类型相互转换;sin_port 和sin_addr 必须是网络字节顺序,因为它们被封装在包的 IP 和UDP 层,而 sin_family不发送到网络上可以是本机字节顺序。
相关函数
1.socket()函数
该函数用于根指定的地址族、数据类型和协议来分配一个套接字的描述字及其所用的资源。
Socket 函数原型为:
int socket( int domain , int type , int protocol ) ;
a、参数 domain 指定地址描述,一般为 AP_INET;
b、参数 type 指定 socket 类型:SOCK_STREAM 和 SOCK_DGRAM;
c、参数 protocol 通常为 0;
d、函数返回值为一个整型 socket 描述符,在 bind 函数中调用。
2.bind()函数
该函数用于将一个本地地址与一个套接字绑定在一起。
int bind( int sockfd , struct sockadd* my_addr , int addrlen) ;
a、sockfd:socket 描述符,使用 socket 函数返回值,将该 socket 与本机
上的一个端口相关联。在设计服务器端程序是需要调用 bind 函数,以在该端
口上监听服务请求;而客户端一般不需要调用 bind 函数,因为只需知道服务
器 IP 地址,并不关心客户通过哪个端口与服务器建立连接,内核会自动选择
一个未被占用的端口供客户端来使用。
b、my_addr:指向包含本机 IP 地址及端口号等信息的 sockaddr 类型的指针。
c、addrlen:sizeof( struct sockaddr)的值。
d、bind 函数返回值:为-1 表示遇到错误,并且 errno 中包含相应的错误码。3.connect()函数与远程服务器建立一个 TCP 连接。
int connect(int sockfd, struct sockaddr* serv_addr, int addrlen);
a、sockfd:目的服务器的 socket 描述符。
b、serv_addr:指向包含目的服务器的 IP 地址及端口号的指针。
c、addrlen:sizeof( struct sockaddr)的值。
d、connect 函数返回值:为-1 表示遇到错误,并且 errno 中包含相应的错误码,进行服务器端程序设计时不需调用 connect 函数。
4.listen()函数
在服务器端程序中,当 socket 与某一端口绑定后,需要监听该端口,
及时处理到达该端口上的服务请求。