前段时间刚开始学习《TCP/IP Sockets编程(C语言实现) (第2版)》一书,又被告知建议先去看一下《UNIX网络编程(第一卷)》的部分内容会对理解其理论知识有所帮助,于是稍微停滞了一下。几天前所练习的实例已经有所生疏,因此为了复习这部分内容(前面所提起的第一本书第2章),此文便作为复习笔记(书本关键内容摘录),而以后各章节的学习也希望能做到及时总结和复习。
本章示例的工作方式:客户连接服务器并发送它的数据;服务器简单地把它接收到的任何内容发送回客户并断开连接。
1.典型的TCP客户的通信步骤
⑴使用socket()创建TCP套接字
参数涉及地址族、使用的协议,正确创建返回一个句柄。
⑵使用connect()建立到达服务器的连接
参数涉及套接字句柄、服务器的地址结构中的地址和端口标识,其中地址结构需要强制转换为泛型类型。
⑶使用send()和recv()通信
send()参数涉及套接字句柄、发送内容、发送长度;返回值为发送的字节数,错误返回为-1。
recv()参数涉及套接字句柄、接收缓冲区、缓冲区大小、调用方式;返回值为接受的字节数,返回0表示另一端应用程序关闭了TCP连接,返回-1表示失败。
⑷使用close()关闭连接
示例为之前提供的下载页面的TCPEchoClient4.c。
2.基本的TCP服务器通信的常规步骤
⑴使用socket()创建TCP套接字
⑵利用bind()给套接字分配端口号
参数涉及套接字句柄、服务器的本机地址结构中的地址和端口标识,其中地址结构需要强制转换为泛型类型,如果不是非常关心所在地址可以用inaddr_any。
⑶使用listen()告诉系统允许对该端口建立连接
参数涉及套接字句柄、最大允许连接数。
⑷反复执行以下操作
参数涉及之前的套接字句柄,创建成功后即将填写的本机地址结构,该地址结构的长度,其中地址结构需要强制转换为泛型类型,返回一个新套接字的句柄。
示例为之前提供的下载页面的TCPEchoServer4.c以及TCPServerUtility.c中的HandleTCPClient()。
3.指定地址
⑴通用地址
struct sockaddr {
sa_family_t sa_family; //Address family (e.g.,AF_INET)
char sa_data[14];
};
⑵IPv4地址
struct in_addr {
uint32_t s_addr;
};
struct sockaddr_in {
sa_family_t sin_family; //Internet protocol (AF_INET)
in_port_t sin_port; //Address port (16bits)
struct in_addr sin_addr; //IPv4 address (32bits)
char sin_zero[8]; //Not used
};
⑶IPv6地址(已按照上一篇文章更改)
struct in_addr {
uint8_t s_addr[16];//Internet address(128bits)
};
struct sockaddr_in6 {
sa_family_t sin6_family; //Internet protocol(AF_INET6)
in_port_t sin6_port; //Address port(16bits)
uint32_t sin6_flowinfo; //Flow information
struct in6_addr sin6_addr;//IPv6 address (128bits)
uint32_t sin6_scope_id; //Scope identifier
};
⑷地址转换
int inet_pton(int addressFamily, constchar*src , void*dst)
//把地址从可打印的字符串(*src)转换为数字(dst引用的地址)
constchar*inet_ntop(int addressFamily, constvoid*src, char*dst,socklen_t dstBytes)
//把地址从数字转化为可打印的形式
⑸获取套接字的关联地址
int getpeername(int socket, struct sockaddr *remoteAddress, socklen_t (addressLength)
int getsockname(int socket, struct sockaddr (localAddress, socklen_t (addressLength)
4.其他
为了便于在同一台计算机的终端上进行调试,需要先在后台执行服务器程序(参数等所有内容的最后面加一个&),再执行客户机程序,发送到127.0.0.1即可。相关调试时用到的进程操作还有ps(查看当前运行进程)、kill(关闭进程)。