最近在学习winsocket整理一下:
IP与端口:
1、网络中有很多的主机,怎么区分主机?
用IP来标识不同的主机,其中现在主要用的是IPV4(32位),随着发展,IPV4无法满足连入的主机数量——地址不够用,所以以后应用更强大的IPV6(128为)。
2、同一台主机中有很多的服务,如何区分不同的服务?
用端口号来区分不同的服务,端口号是一个整数,范围是:0 ~ 65535;对应于TCP和UDP有相应的TCP端口和UDP端口
其中:0-1023为通用端口,这些端口已经绑定了某些服务;
1024-49151 为已注册端口号,供一般程序使用,我们开发winsocket程序时使用这个范围内的端口;
49152-65535为动态或私有端口
在winsocket中套接字SOCKET的定义:
typedef unsigned int u_int;
typedef u_int SOCKET;
从上面的定义我们可以得知其实,SOCKET就是一个无符号的整数,并且INVALID_SOCKET是唯一一个无效的套接字,其他所有的 0 - INVALID_SOCKET-1都是有效的(INVALID_SOCKET = 4294967295,这是我直接把INVALID_SOCKET打印出来的结果);由于INVALID_SOCKET是一个无效的套接字,所以我们可以利用这个值来判断我们创建的套接字是否有效。
INVALID_SOCKET的申明:#define INVALID_SOCKET (SOCKET)(~0)
一、TCP套接字基础
基本的模式:
Server端:创建socket->绑定地址->设置为监听->接受链接->交互数据(收发数据)->关闭
Client端:创建socket->连接服务器->交互数据(收发数据)->关闭
<span style="font-size:14px;">//Server端
#include<iostream>
#include <WINSOCK2.H>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
//<1>创建Socket
WORD wVersionRequested;//版本
WSADATA wsaData;//
int nErrorCode;//错误代码
wVersionRequested = MAKEWORD(2, 2);//生成版本
nErrorCode = WSAStartup(wVersionRequested, &wsaData);
if (nErrorCode != 0)
{//winsocket异步套接字启动失败情况
cout << "WinSocket fail startup!" << endl;
return 1;
}
//check version
if (LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();//delete data
return 1;
}
SOCKET sockServer;
sockServer = socket(AF_INET, SOCK_STREAM, 0);
//<2>绑定地址
SOCKADDR_IN addrServer;
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(8888);
bind(sockServer, (SOCKADDR *)&addrServer, sizeof(SOCKADDR));
//<3>打开监听
listen(sockServer, 5);
SOCKADDR_IN addrClient;
int nLen = sizeof(SOCKADDR);
cout << "here is Server" << endl;
while (true)
{
//<4>接受链接
SOCKET sockConn = accept(sockServer, (SOCKADDR *)&addrClient, &nLen);
char sendBuf[1024] = {0};
sprintf_s(sendBuf, sizeof(sendBuf), "Welcome %s to here!\nwhat can I help you?");
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);
char recvBuf[1024] = {0};
//<5>数据交互
while (true)
{
//收数据
recv(sockConn, recvBuf, sizeof(recvBuf) - 1, 0);
cout << "Client: " << recvBuf << endl;
if (recvBuf[0] == 'n'){ break; }
cout << "Server: ";
cin >> sendBuf;
//发数据
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);
}
//<6>关闭socket
closesocket(sockConn);
}
system("pause");
return 0;
}</span>
<span style="font-size:14px;">//Client端
#include<iostream>
#include<WINSOCK2.H>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
//<1>创建socket
WORD wVersion;
WSADATA wsaData;
int nErrorCode;
wVersion = MAKEWORD(2, 2);
nErrorCode = WSAStartup(wVersion, &wsaData);
if (nErrorCode != 0)
{
cout << "WinSocket fail startup !" << endl;
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup();
return 1;
}
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrServer;
addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(8888);
//<2>链接服务器
connect(sockClient, (SOCKADDR *)&addrServer, sizeof(SOCKADDR));
char sendBuf[1024] = { 0 };
char recvBuf[1024] = { 0 };
cout << "here is Client !" << endl;
//<3>数据交互
while (true)
{
//收
recv(sockClient, recvBuf, sizeof(recvBuf) - 1, 0);
cout << "Server: " << recvBuf << endl;
if (recvBuf[0] == 0)
{
break;
}
cout << "Client: ";
cin >> sendBuf;
//发
send(sockClient, sendBuf, strlen(sendBuf) + 1, 0);
}
//<4>关闭socket
closesocket(sockClient);
WSACleanup();
system("pause");
return 0;
}</span>
二、UDP套接字基础
server端:创建socket->绑定地址->数据交互->关闭
Client端:创建socket->数据交互->关闭