前段时间刚开始学习《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()告诉系统允许对该端口建立连接

  参数涉及套接字句柄、最大允许连接数。

⑷反复执行以下操作

调用accept()为每个客户连接获取新的套接字

  参数涉及之前的套接字句柄,创建成功后即将填写的本机地址结构,该地址结构的长度,其中地址结构需要强制转换为泛型类型,返回一个新套接字的句柄。

使用send()和recv()通过新的套接字与客户通信
使用close()关闭客户连接


示例为之前提供的下载页面的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(关闭进程)。


作者:五岳

出处:http://www.cnblogs.com/wuyuegb2312

对于标题未标注为“转载”的文章均为原创,其版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。