我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。
能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。
客户端代码:
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,“ws2_32.lib”)
int main()
{
//SOCKET前的一些检查,检查协议库的版本,为了避免别的版本的socket,并且通过
//WSAStartup启动对应的版本,WSAStartup的参数一个是版本信息,一个是一些详细的细节,注意高低位
//WSAStartup与WSACleanup对应
int err;
WORD versionRequired;
WSADATA wsaData;
versionRequired=MAKEWORD(1,1);
err=WSAStartup(versionRequired,&wsaData);//协议库的版本信息
//通过WSACleanup的返回值来确定socket协议是否启动
if (!err)
{
printf("客户端嵌套字已经打开!\n");
}
else
{
printf("客户端的嵌套字打开失败!\n");
return 0;//结束
}
//创建socket这个关键词,这里想一下那个图形中的socket抽象层
//注意socket这个函数,他三个参数定义了socket的所处的系统,socket的类型,以及一些其他信息
SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
//socket编程中,它定义了一个结构体SOCKADDR_IN来存计算机的一些信息,像socket的系统,
//端口号,ip地址等信息,这里存储的是服务器端的计算机的信息
SOCKADDR_IN clientsock_in;
clientsock_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
clientsock_in.sin_family=AF_INET;
clientsock_in.sin_port=htons(6000);
//前期定义了套接字,定义了服务器端的计算机的一些信息存储在clientsock_in中,
//准备工作完成后,然后开始将这个套接字链接到远程的计算机
//也就是第一次握手
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接
char receiveBuf[100];
//解释socket里面的内容
recv(clientSocket,receiveBuf,101,0);
printf("%s\n",receiveBuf);
//发送socket数据
send(clientSocket,"hello,this is client",strlen("hello,this is client")+1,0);
//关闭套接字
closesocket(clientSocket);
//关闭服务
WSACleanup();
return 0;
}
对应的服务端代码:
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,“ws2_32.lib”)
int main()
{
//创建套接字,socket前的一些检查工作,包括服务的启动
WORD myVersionRequest;
WSADATA wsaData;
myVersionRequest=MAKEWORD(1,1);
int err;
err=WSAStartup(myVersionRequest,&wsaData);
if (!err)
{
printf(“已打开套接字\n”);
}
else
{
//进一步绑定套接字
printf(“嵌套字未打开!”);
return 0;
}
SOCKET serSocket=socket(AF_INET,SOCK_STREAM,0);//创建了可识别套接字
//需要绑定的参数,主要是本地的socket的一些信息。
SOCKADDR_IN addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址
addr.sin_port=htons(6000);//绑定端口
bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//绑定完成
listen(serSocket,5);//其中第二个参数代表能够接收的最多的连接数
SOCKADDR_IN clientsocket;
int len=sizeof(SOCKADDR);
while (1)
{
//第二次握手,通过accept来接受对方的套接字的信息
SOCKET serConn=accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果这里不是accept而是conection的话。。就会不断的监听
char sendBuf[100];
sprintf(sendBuf,"welcome %s to bejing",inet_ntoa(clientsocket.sin_addr));//找对对应的IP并且将这行字打印到那里
//发送信息
send(serConn,sendBuf,strlen(sendBuf)+1,0);
char receiveBuf[100];//接收
recv(serConn,receiveBuf,strlen(receiveBuf)+1,0);
printf("%s\n",receiveBuf);
closesocket(serConn);//关闭
WSACleanup();//释放资源的操作
}
return 0;
}