对于编程者来说,我们所见到的网络通信实际上是2个socket之间的通信。所以双方第一步会调用socket创建socket。此时系统内核会创建一个socket描述结构并返回该描述结构的描述字。对于服务器来说,系统自己创造的socket并不适合,因为我们要指定服务器socket的端口号,因此我们会调用bind函数,将我们自己定义的描述结构绑定到描述关键字上。对于客户端来说一般系统自己制定描述结构即可,因此调用bind函数没有什么太多的意义,但可以调用。但貌似指定指定通信的端口号,地址貌似没有意义。
1.socket函数。
int socket(int family, int type, int protocol);
返回socket描述字。
family指协议族:AF_INET IPV4协议,AF_INET6 IPV6协议, AF_LOCAL UNIX域协议, AF_ROUTE路由套接口协议, AF_KEY 密钥套接口协议。
type: SOCK_STREAM 字节流套接口, SOCK_DGRAM数据报套接口,SOCK_RAW 原始套接口。
protocol:一般设置为0,只有当使用原始套接口时候才有其它设置。
family和type组合
AF_INET AF_INET6 AF_LOCAL AF_ROUTE AF_KEY
SOCK_STREAM TCP TCP YES
SOCK_DGRAM UDP UDP YES
SOCK_RAW IPV4 IPV6 YES YES
TCP和UDP很容易理解,IPV4和IPV6应该是IP数据包通信方面。YES表示有效,但没有合适缩略词描述,空白表示无效组合。(还有可能其它的如PF_XXX或者AF_UNIX,这里没有列出)。
2.connect函数:客户端使用,用于建立一个与TCP服务器的连接。
int connect(int sockfd, const struct sockaddr * servaddr, socklen_t addrlen);返回0成功,返回-1出错。
sockfd:前面提到的描述字。
servaddr:服务器的套接口地址结构指针。
addrlen:地址结构指针的大小。
这个函数很简单。
这里没有指定从哪个端口连接服务器端口,因为内核会自动选择源地址和一个临时端口。至于绑定端口,看下面的bind函数。
connect会触发三路握手,具体的返回错误信息,这里就不列出了。
3.bind函数:给套接口分配一个本地的协议地址。
int bind(int sockfd, struct sockaddr * myaddr, socklen_t addrlen); 0成功,-1出错。
在socket函数中就已经创建了套接口socket,但此时的套接口是有系统指定的IP和端口号。有时我们需要自己来制定地址和端口号,这就通过bind函数,将自己的socket绑定到套接口描述字上。上面的函数参数就很容易理解了,addrlen表示的是myaddr的长度。
myaddr有3个信息,协议族,地址和端口号。
对于服务器来说:绑定端口号很明显,因为只有知道端口号,我们才能去和服务器通信,当然不绑定也是可以的,这样你就得通过其它办法获得端口号比如说询问网络管理员。绑定IP地址就比较令人费解。服务器绑定IP地址的意义,比如说局域网内,该服务器地址为192.168.1.2,如果你把该地址绑定入socket,那么其它机器就可以通过192.168.1.2来访问。但对于本机来说,它还可以通过127.0.0.1来访问,但此时链接失败,因为你绑定的地址是192.168.1.2而不是127.0.0.1。当然如果你在路由器上做了端口映射,但外网仍然不可以访问你的这台机器服务器进程。
对于客户端来说:一般我们不需要去绑定一个自定义的socket,因为系统分配的已经满足我们传输要求。绑定IP地址貌似没什么意义,但绑定端口会有一定作用,因为平常是有系统自动分配的端口去和服务器通信,如果你绑定了端口号,则你就会通过指定的端口号和对方通信。
4.listen函数
int listen(int sockfd, int backlog) 返回0成功,-1出错
listen将未连接的套接口转换成监听套接口,第2个参数则是指此套接口最大的排队数目。但backlog定义比较模糊,具体的需要man listen查询,每个系统在实现上各不相同。但想用此参数来限制链接数目是不现实的。
5.accept函数
int accept(int sockfd, struct sockaddr * cliaddr, socket_t * addrlen); 返回非负描述字, -1就是出错。
从已完成队列头返回下一个已完成队列,若已完成队列空,则进程睡眠(缺省阻塞方式)。参数cliaddr会返回客户端信息,而addrlen则返回该结构的大小(已写数据的大小))。
如果你希望刚刚的程序显示连接者的信息,你所需要加入的代码则是
struct sockaddr_in * client_socket; //IPV4地址套接口描述结构
socket_len len; //长度
char temp[30]; //用来存点十表示法的IP地址,只要IPV4只要大于16即可
connfd = accept(listenfd, (struct sockaddr *)client_socket, &len); //修改的部分
inet_ntop(AF_INET, &client_socket->sin_addr, temp, sizeof(temp)); //将client_socket中记录的IP地址变成点十进制,结果存在temp中,同时返回char *也会指向temp
printf("connection from %s, port %d\n", temp, ntohs(client_socket->sin_port));
关于返回值,返回非负的值,则这个值代表了与客户的TCP链接。这里listenfd代表监听套接口描述字,而connfd代表了已连接套接口描述字。比如说服务器和2个客户端通信,服务器IP地址为192.168.1.3,服务器进程监听的端口号是80,2台客户机分别是192.168.1.4和192.168.1.5.内核分配给他们通信的端口号分别为45173和45765。这里IP地址代表了机器,80号端口则代表的是进程(可以这么理解,只要是提交到192.168.1.3:80的请求,就是请求服务器进程服务)。此时链接建立,connfd则代表了链接,这里有2个客户机连接上了服务器,则会有2个connfd。以后传递数据就通过这个链接描述字。
6.close函数
close函数并不会触发客户端或者服务器发送结束字节fin,它只是将链接的共享计数减1,当共享计数减为0时候,才会触发客户端或者服务器发送结束字节fin.及时你调用了close并最终导致计数减为0,socket也会将剩余没有发送完的数据发送完毕后才会发送fin字节。
分享到:
相关推荐
使用单进程和 select 的 TCP 服务器的主要功能是创建 TCP 套接口、捆绑服务器众所周知端口到套接口、把套接口变成监听套接口、调用 select 初始化数据结构、阻塞于 select、若监听套接字变为可读,accept 新的连接、...
5. 套接字编程:介绍了如何使用套接字API进行网络编程,讲解了套接字接口的使用方法以及如何在不同的编程语言中实现网络通信。 本书第二版的发布日期为2011年11月。这本书是计算机网络领域的学习者和专业人士的宝贵...
在“TCP.rar”这个压缩包中,很可能是包含了一些关于TCP编程的示例代码或教程,帮助开发者理解和实现TCP套接字编程。 TCP编程的核心概念包括以下几个方面: 1. **连接建立**:TCP采用三次握手(Three-Way ...
3. **TCP连接**:TCP连接建立需要经过“三次握手”,确保双方都有能力进行数据传输。连接建立后,数据以字节流的形式发送,通过序列号和确认应答保证数据的可靠传输。关闭连接时,使用“四次挥手”释放资源。 4. **...
Winsock是Windows操作系统对Berkeley套接字API的实现,提供了与平台无关的网络编程接口。通过调用Winsock的函数,如`socket()`、`bind()`、`listen()`、`accept()`、`connect()`、`send()`和`recv()`等,可以构建TCP...
在这份“基于TCP的Socket编程.pdf”的资料中,主要讨论了使用Java语言如何实现基于TCP的Socket编程。 知识点主要包括以下几个方面: 1. Java中的Socket API - Java的Socket API提供了丰富的网络通信功能。Socket...
在TCP/IP编程中,Socket是操作系统提供的接口,允许应用程序通过它来实现网络通信。Socket分为两种类型:流套接字(Stream Socket)对应于TCP协议,提供顺序、可靠的数据传输;数据报套接字(Datagram Socket)对应...
1. 创建套接字:使用socket库创建一个TCP套接字,如`socket.socket(socket.AF_INET, socket.SOCK_STREAM)`。 2. 绑定地址:使用`bind()`方法绑定IP和端口号,让服务端在特定的网络位置等待连接。 3. 监听连接:使用`...
2. 绑定:TCP套接字需要绑定到特定的IP地址和端口号,而UDP套接字通常绑定到INADDR_ANY(任何可用IP地址)和指定端口。 3. 连接/监听:TCP客户端套接字发起连接请求,服务器套接字进行监听。 4. 数据收发:TCP和UDP...
3. Socket 编程:提供了灵活的网络编程接口,用于实现 TCP/IP 网络通信。 Linux 的 TCP/IP 网络通信编程方法具有广泛的应用前景,特别是在嵌入式系统开发中。 Linux 作为一个自由软件,具有内核小、效率高、源代码...
C++中进行TCP/IP编程,通常会用到socket API,这是操作系统提供的接口,用于创建、绑定、监听、连接和发送/接收数据。在Windows平台下,可以使用Winsock库,而在Unix/Linux系统中,可以使用标准的Berkeley套接字API...
本主题将详细探讨如何使用C语言进行TCP套接字编程,包括服务器端和客户端的实现。 一、TCP套接字编程基础 1. 套接字库与函数: 在C语言中,我们主要依赖`<sys/socket.h>`和`<netinet/in.h>`头文件中的函数来实现套...
在"TCP_text"这个文件中,可能包含了关于如何在Linux下实现这些步骤的代码示例,包括如何打开文件、读取文件内容、打包成字节流,然后通过TCP套接字将字节流发送给远程服务器,以及服务器如何接收并解码字节流,最终...
3. **IP分片与重组**:当数据包过大无法通过某个网络接口传输时,IP会将其分片发送,接收端再重组。 高级TCP/IP编程涉及的内容广泛,包括但不限于: 1. **多路复用与多路分解**:使用socket API的select、poll或...
Windows环境下的TCP/IP编程主要依赖于Windows Socket API,简称Winsock,它为开发者提供了与平台无关的接口来实现TCP通信。本篇文章将深入探讨Windows下利用Winsock进行TCP/IP编程的关键知识点。 首先,我们来看`...
基于TCP文件传输控制台程序.zip 套接口编程 这是个控制台程序 基于TCP的文件传输 代码比较简洁 博客有介绍 地址: http://blog.csdn.net/xsl1990/article/details/8478527
本书致力于Ruby语言下的TCP套接字编程,详细介绍了使用Ruby进行网络编程的相关知识,特别是围绕TCP协议进行的套接字编程。 首先,书中对贝克利套接字API进行了介绍,这是一种广泛使用的用于网络编程的接口。书中并...
3. Java中的网络编程:本书专注于如何在Java环境中进行Socket编程。Java提供了一套丰富的网络API,使得开发者能够方便地创建网络应用程序。学习内容会包括***包中的类和接口,例如Socket类、ServerSocket类以及它们...
### UNIX网络编程(第2版)第1卷_套接口API和XOpen传输接口API3 #### 套接口(Socket)API概述 在《UNIX网络编程》(第2版)第一卷中,作者深入探讨了套接口API,这是UNIX系统进行网络通信的基础。套接口是一种用于...