win32_c++_socket
总阅读次
服务器
: 它是被动的,它只能等待别人跟它建立连接,自己不会去主动连接;
[MAKEWORD(2,2)使用][]
[[MAKEWORD(2,2)使用]: http://blog.sina.com.cn/s/blog_a74f39a201010sb3.html
Windows Socket和Linux Socket编程的区别
基础概念
- TCP/IP协议族
英语:TCP/IP Protocol Suite,或TCP/IP Protocols),简称TCP/IP
因为该协议家族的两个核心协议:TCP(传输控制协议)和IP(网际协议),为该家族中最早通过的标准[3]。由于在网络通讯协议普遍采用分层的结构,当多个层次的协议共同工作时,类似计算机科学中的堆栈,因此又被称为TCP/IP协议栈(英语:TCP/IP Protocol Stack)
端口
端口就是特定的程序或者软件也可以理解为特定软件或程序的接口,原端口/目的端口
源端口
就是本机程序用来发送数据的端口,目的端口
就是对方主机用哪个端口接收;封目的端口自己就出不去,封源端口别人就进不来。
数据发送时计算机会在数据段上添上本机端口号(源端口号)和目的主机接收数据的端口号(目的端口号)
数据包通过网络设备走的时候,第一个检查的就是你这个数据包的目的地址在什么地方。
- TCP通信3个步骤:
1)建立TCP连接很简单,通过三次握手便可建立连接。
2)建立好连接后,开始传输数据。TCP数据传输牵涉到的概念很多:超时重传、快速重传、流量控制、拥塞控制等等。
3)断开连接的过程也很简单,通过四次握手完成断开连接的过程。
- TCP三次握手建立连接
第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
ACK
用于确认资料有无正确的传输到接收端,在ASCII中编号为6网络中进程之间如何通信
网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。
- 侦听端口
服务器倾听端口 ,是服务器监听客户端用的 ,相当于”地址” ,是服务器与客户端间的纽带
TCP/IP首先要有一个服务端
,它是被建立连接的;
WSAStartup
WSAStartup就是为了向操作系统说明,我们要用哪个库文件,让该库文件与当前的应用程序绑定,从而就可以调用该版本的socket的各种函数了。
WSAStartup() - 使用方法
当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。
socket
Windows 下也使用 socket() 函数来创建套接字,原型为:
1 | SOCKET socket(int af, int type, int protocol); |
除了返回值类型不同,其他都是相同的。Windows 不把套接字作为普通文件对待,而是返回 SOCKET 类型的句柄。请看下面的例子:
1 | SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字 |
- af 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF 是“Address Family”的简写,INET是“Inetnet”的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。
- type 为数据传输方式,常用的有 SOCK_STREAM 和 SOCK_DGRAM,在《socket是什么意思》一节中已经进行了介绍。
- SOCK_STREAM 表示面向连接的数据传输方式。数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢。常见的 http 协议就使用 SOCK_STREAM 传输数据,因为要确保数据的正确性,否则网页不能正常解析。
- SOCK_DGRAM 表示无连接的数据传输方式。计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。因为 SOCK_DGRAM 所做的校验工作少,所以效率比 SOCK_STREAM 高。
- SOCK_STREAM 表示面向连接的数据传输方式。数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢。常见的 http 协议就使用 SOCK_STREAM 传输数据,因为要确保数据的正确性,否则网页不能正常解析。
- protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。
bind
函数
调用函数 socket 创建套接字描述符时,该套接字描述符是存储在它的协议族空间中,没有具体的地址,要使它与一个地址相关联,可以调用函数bind 使其与地址绑定。客户端的套接字关联的地址一般可由系统默认分配,因此不需要指定具体的地址。若要为服务器端套接字绑定地址,可以通过调用函数 bind 将套接字绑定到一个地址。下面是该函数的描述:
1 | /* 套接字的基本操作 */ |
#pragma comment(lib, “ws2_32.lib”)
1 |
|
SO_REUSEADDR
1 |
|
recv(sHost, bufRecv,5 , 0); // 接收服务器端的数据, 只接收5个字符
cout << endl <<"从服务器接收数据:" << bufRecv;
}
//退出
1 |
|
auto len = recv(sHost, bufRecv, BUF_SIZE, 0); // 接收服务器端的数据, 只接收5个字符 // client4: 读
bufRecv[len] = 0;
cout << endl << "从服务器`接收数据:" << bufRecv;
}
//退出
1 |
|
char bufRecv[100] = { 0 };
recv(sHost, bufRecv, 100, 0);
1 |
|
ZeroMemory(bufRecv, BUF_SIZE); //清0 /*或者这样: memset(bufRecv, 0, BUF_SIZE);*/
recv(sHost, bufRecv, BUF_SIZE, 0);
1. 是不是说char数组没有结尾`\0`输出会出现乱码?
2. server端,send数组明明有``\0``但是client端的rev却没有接收到``\0``?
[需要了解_c语言——'\0','0',"0" ,0之间的区别][]
[需要了解_c语言——'\0','0',"0" ,0之间的区别]: http://blog.sina.com.cn/s/blog_73428e9a0101bdkh.html
[需要了解_字符和字符字面值][]
[需要了解_字符和字符字面值]: http://blog.csdn.net/candcplusplus/article/details/8264676
[CSDN类似问题][]
[CSDN类似问题]: http://bbs.csdn.net/topics/390408164