赞
踩
实现两台或多台已经联网的计算机互相交换数据的行为,就是网络编程.
我们日常使用的操作系统已经为我们提供了socket, 不需要熟悉网络数据传输的原理,
也能掌握网络编程.
Linux
通常会用文件描述符
来表示或区分已经打开了的文件;windows
通过文件句柄
的方式来表示,和上述的Linux
的文件描述符
是类似的概念;Linux
的一切都是文件,所以网路连接也是一个文件.Windows
则会将socket
和文件区分开来,因此在Windows
中socket
有针对性设计的数据传输函数.
面向连接的套接字(Stream Sockets)
,是对SOCK_STREAM
的说明.
使用了TCP
协议,有自己的纠错机制.
浏览器使用的http
协议就是基于面向连接的套接字
无连接的套接字(Datagram Sockets)
,也叫数据报格式套接字
.
它的传输效率相对于SOCK_STREAM
要高,但对数据的校验工作较少.
视频聊天和语音视频大多是采用无连接套接字
来传输数据的.
原始套接字(raw-protocol interface)
.
保存了数据包的完整IP
头,可以通过它来对数据进行分析.
网络安全产品通常使用此类型,如MAC
地址扫描器,网络嗅探器等产品.
#include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; int main() { //初始化套接字库 WORD wVersion; WSADATA wsaData; int err; wVersion = MAKEWORD(1, 1); err = WSAStartup(wVersion, &wsaData); //检查 if (err != 0) { return err; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { //清理套接字库 WSACleanup(); return -1; } //创建套接字 SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); //准备绑定的信息 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); //绑定到本机 bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); //监听 listen(sockSrv, 10); cout << "server start at prot: 6000" << endl; SOCKADDR addrCli; int len = sizeof(SOCKADDR); char recvBuf[100]; char sendBuf[100]; while (true) { //接受连接请求 SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrCli, &len); sprintf_s(sendBuf,100, "hello"); send(sockConn, sendBuf, strlen(sendBuf) + 1, 0); //接受或发送数据 recv(sockConn, recvBuf, 100, 0); std::cout << recvBuf << std::endl; //关闭套接字 closesocket(sockConn); } //关闭套接字 closesocket(sockSrv); //清理套接字库 WSACleanup(); system("pause"); return 0; }
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; int main() { //初始化套接字库 WORD wVersion; WSADATA wsaData; int err; wVersion = MAKEWORD(1, 1); err = WSAStartup(wVersion, &wsaData); //检查 if (err != 0) { return err; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { //清理套接字库 WSACleanup(); return -1; } //创建tcp套接字 SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.0.131"); //addrSrv.sin_addr.S_un.S_addr = htons(6000);//大失误 addrSrv.sin_port = htons(6000); addrSrv.sin_family = AF_INET; //连接服务器 connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char sendBuf[] = "world"; char recvBuf[100]; //发送数据到服务器 send(sockCli, sendBuf, strlen(sendBuf) + 1, 0); //接收服务器发送的数据 recv(sockCli, recvBuf, sizeof(recvBuf), 0); cout << recvBuf << endl; closesocket(sockCli); WSACleanup(); system("pause"); return 0; }
#include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; int main() { //初始化套接字库 WORD wVersion; WSADATA wsaData; wVersion = MAKEWORD(1, 1); int err = WSAStartup(wVersion, &wsaData); //检查 if (err != 0) { cout << WSAGetLastError() << endl; return err; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { cout << WSAGetLastError() << endl; WSACleanup(); return -1; } //创建套接字 SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_port = htons(6002);//主机字节序转换 addrSrv.sin_family = AF_INET; //绑定到本机6002端口 bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); //接受请求,处理请求 SOCKADDR_IN addrCli; int len = sizeof(SOCKADDR); char sendBuf[] = "UDP Server ..."; char recvBuf[100]; cout << "Start UDP Server with port 6002 " << endl;; while (true) { //接收数据 recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrCli, &len); cout << "Recv: " << recvBuf << endl; //发送数据 sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrCli, len); cout << "Send: " << sendBuf << endl; } //关闭套接字并清除套接字库 closesocket(sockSrv); WSACleanup(); system("pause"); return 0; }
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; int main() { //初始化套接字库 WORD wVersion; WSADATA wsaData; wVersion = MAKEWORD(1, 1); int err = WSAStartup(wVersion, &wsaData); //检查 if (err != 0) { return err; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } //创建UDP套接字 SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_port = htons(6002); addrSrv.sin_family = AF_INET; SOCKADDR_IN addrCli; int len = sizeof(SOCKADDR); char sendBuf[] = "send from UDP client ..."; char recvBuf[100]; //发送数据到服务端并打印 cout << "send to server: " << sendBuf << endl; sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrSrv, len); //接收服务端数据并打印 recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR*)&addrCli, &len); cout << "receve from: " << recvBuf << endl; //关闭套接字并清除套接字库 closesocket(sockCli); WSACleanup(); system("pause"); return 0; }
是
Windows
操作系统特有的函数.
在Windows
系统中使用网络编程需要加载ws2_32.dll
动态链接库.
使用这个dll
之前需要调用WSAStartup()
函数初始化动态库.
函数原型:
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
程序使用
socket
函数来创建套接字,不管是Linux
还是Windows
都一样,区别是返回值不同.
Linux
中socket
函数的返回值是int
,Windows
里的返回值是SOCKET
.
我这里练习的环境是windows
,所以这里的代码例子都以Windows
为准.
函数原型:
SOCKET socket(int af, int type, int protocol);
创建完套接字之后需要确定套接字的各种属性,比如
IP
地址,端口等信息.
这些信息用一个sockaddr
结构体变量存放.
函数原型:
int bind(SOCKET sock, const struct sockaddr *addr, int addrlen);
是客户端在创建完套接字后,用来建立连接的.
它的参数和bind
相同.
函数原型:
int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen);
在服务端绑定完套接字之后,还使用
listen
函数让套接字进入被动监听状态.
第二个参数是请求队列的最大长度.
函数原型:
int listen(SOCKET sock, int backlog);
套接字通过
listen
函数进入被动监听状态之后,通过accept
函数接收客户端请求.
它的参数跟listen
和connect
函数相同.
函数原型:
SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen);
经过上面一系列的连接的目的,自然是为了实现服务端与客户端之间的发送和接收数据.
send
函数是从服务端发送数据,第四个参数可以参考send recv函数中的flags参数
函数原型:
int send(SOCKET sock, const char *buf, int len, int flags);
recv
函数的功能是从服务端或客户端接收数据.
它和send
函数的参数是一样的.
函数原型:
int recv(SOCKET sock, char *buf, int len, int flags);
这篇博客内容只是简单的涵盖了socket
编程需要用到的函数,
以及给出了简单的示例代码.对于socket
编程入门还是有帮助的.\
Windows
操作系统拓展的套接字函数一般以WSA
开头,它的意思是Windows socket API
.常用的比如:
WSASend
,WSARecv
以及前面提到的WSACleanup
等.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。