Windows Sockets网络编程(0)TCP In Action

本文介绍Windows Sockets(Winsock)进行TCP网络编程的基本步骤,包括客户端的WSAStartup、socket、connect,服务器端的bind、listen、accept,以及send、closesocket和WSACleanup等关键函数的使用。通过实例代码解析TCP连接过程,帮助理解TCP的可靠性和连接管理。
摘要由CSDN通过智能技术生成

在谢希仁的《计算机网络》一书中,详尽的学习了网络协议七层塔。也明白了在TCP/IP协议中,可靠性是由传输层来保证的,而传输层的两大协议UDP与TCP,都是在基于网络层IP协议的基础上首次提供端到端的通信。其中,UDP是使用数据报提供服务的,而TCP则提供可靠的流服务。UDP提供的是不可靠的服务(相当于篮球运动员,直接将球扔向篮筐,不关注结果),TCP提供的是可靠的服务(投球不中,将一直投,知道投中为止)。在网络传输过程中,TCP的可靠性很大部分是由重传与确认机制来保证的。要了解更多的知识可以看我的下一篇文章《Windows Sockets网络编程(1)TCP select & thread》、也可以去关注一下《Windows Sockets网络编程(2)TCP Stream拆分、拼接》了解更多TCP流分割知识。


目录:


“谁忽视了TCP,谁注定要推倒重来”——FTP创始人James Van Bokkelen.


How to create a tcp connection

client

WSAStartup

这个函数主要是用来加载Socket库,俩参数,

WSAStartup(
      _In_ WORD wVersionRequired,
      _Out_ LPWSADATA lpWSAData);
  • wVersionRequired,指明需要的Socket版本;一般使用宏MAKEWORD(2,2)。

  • lpWSAData,是一个输出变量,指系统实际返回的库信息。

SOCKET _tcp_socket;
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0){
    perror("WSASartup error !");
}

socket

创建socket,函数原型是这样滴,

socket (
       _In_ int af,
       _In_ int type,
       _In_ int protocol);
  • af 协议族,常用的协议族有AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域Socket)、AF_ROUTE等。
  • type Socket类型,常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。
    • TCP ,流式Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。
    • UDP,数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
  • protocol 指定协议,常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

注意:type和protocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。

_tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_tcp_socket == INVALID_SOCKET){
    perror("socket error !");
    WSACleanup();
}

sockaddr_in

我更喜欢将变量定义为xxx_config,因为在我看来,这很大程度上就相当于一个配置文件,

struct sockaddr_in {
      short   sin_family;
      u_short sin_port;
      struct  in_addr sin_addr;
      char    sin_zero[8];
};
  • sin_family 地址家族,通常大多用的是都是AF_INET,代表TCP/IP协议族。
  • sin_port 端口,这里必须采用网络数据格式,
    • htons ,将端口号由主机字节序转换为网络字节序的整数值。
  • sin_addr 存储IP地址,这里服务端和客户端是有所区别的。
    • inet_addr 客户端使用,将一个IP字符串转化为一个网络字节序的整数值,用于sockaddr_in.sin_addr.s_addr。
    • htonl(INADDR_ANY) 服务端使用,INADDR_ANY表示任何IP地址。
SOCKADDR_IN remote_config;
remote_config.sin_port = htons(port);
remote_config.sin_family = AF_INET;
remote_config.sin_addr.S_un.S_addr = inet_addr(addr);

connect

TCP客户端使用它,通过调用connect建立一个连接(虚电路),

int PASCAL FAR connect (
    _In_ SOCKET s,
    _In_reads_bytes_(namelen) const struct sockaddr FAR *name,
    _In_ int namelen);

无需赘言,按照以下方式调用。如果调用失败(SOCKET_ERROR),不要重新调用connect,最好closesocket然后socket重新得到一个新的,继而进行connect。

如果客户端通过WSAGetLastError获得返回值(10061),可能是,

  • 服务端没有运行。
  • IP端口设置有误。

另外,一般UDP客户端不需要调用调用connect,但也并不是不可以。这里,如果调用两次及以上次数connect函数,将造成(10048)错误。


                
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值