1.描述:使用socket编程完成数据传输
1.1 TCP / IP三次握手
1客户端向服务器发送信息SYN J
2.服务器接受到之后 向客户端发送 ack J+1 来告诉客户端服务器能接收到正确的信息 同时发送SYN K给客户端
3.客户端返回ack K+1 给服务器来告诉服务器 它能接收到正确的信息
1.2 客户端 服务器端 流程图
2.服务端代码实现
手动添加 ws2_32.lib库
#include <iostream>
#include <Windows.h>
#include <string>
#include <WinSock.h>
using namespace std;
int main(int argc , char* argv[])
{
//初始化WSA
WSADATA ws;
WSAStartup(MAKEWORD(2,2), &ws);
//创建socket
SOCKET sock = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);//AF_INET->tcp/ip 协议,SOCK_STREAM ->tcp协议
if (sock == INVALID_SOCKET)
{
cout<<"create socket failed!"<<endl;
}
else
{
cout<<sock<<endl;
}
sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(99999);//本地字节序 -> 网络字节序
saddr.sin_addr.S_un.S_addr = INADDR_ANY;//绑定ip地址,0表示任意ip地址都可以访问
if(bind(sock, (LPSOCKADDR)&saddr, sizeof(saddr)) == SOCKET_ERROR)
{
cout<<"bind port failed!"<<endl;
}
else
{
cout<<"bind port success!"<<endl;
}
/*
面向连接的服务器 使用它将一个套接字置为被动模式,并准备接收传入链接,用于服务器,指明某个套接字连接是被动的
*/
//开始监听
if(listen(sock,10) == SOCKET_ERROR)//第一个参数:指明创建连接的套接字,第二个参数:该套接字使用的队列长度,指定在请求队列中允许的最大请求数
{
cout<<"listen error!"<<endl;
}
else
{
cout<<"listen success!"<<endl;
}
//循环接收数据
sockaddr_in caddr;
int caddrLen = sizeof(caddr);
char revData[1024]={0};
while (true)
{
cout<<"等待连接..."<<endl;
/*
功能:获取传入连接的请求,返回新的连接的套接字描述符
为每个新的连接请求创建一个新的套接字,服务器值对新的连接使用该套接字,原来的监听套接字接受其它连接请求
新的连接上传输数据使用新的套接字,使用完毕,服务器将关闭这个套接字
参数:第一个参数:指明正在监听的套接字
第二个参数:提出连接请求的主机地址
第三个参数:地址长度
*/
SOCKET newSock = accept(sock, (sockaddr*)&caddr,&caddrLen);//sock只用于连接,连接成功之后accept会生成一个新的sock用于通信
if (newSock == INVALID_SOCKET)
{
cout<<"accept error!"<<endl;
continue;
}
else
{
cout<<"有新的连接:"<<inet_ntoa(caddr.sin_addr)<<endl;
//接收数据
while (1)
{
int recvLen = recv(newSock, revData,sizeof(revData)-1,0);
if (recvLen <= 0)break;
if (strstr(revData,"quit") != NULL)
{
cout<<"对方已断开连接.."<<endl;
break;
}
cout<<"message from client:"<<revData<<endl;
//发送数据
string data;
cin>>data;
if (data == "quit")
{
cout<<"结束会话!"<<endl;
break;
}
const char* sendData;
sendData = data.c_str();//string ->const char*
send(newSock, sendData , strlen(sendData),0);//发送数据
}
closesocket(newSock);
break;
}
}
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}
3.客户端代码实现
#include <WinSock.h>
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
int main(int argc, char* argv[])
{
WSADATA ws;
WSAStartup(MAKEWORD(2,2), &ws);
//创建socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
cout<<"create socket failed!"<<endl;
}
else
{
cout<<sock<<"create success!"<<endl;
}
sockaddr_in caddr;
caddr.sin_family = AF_INET;
caddr.sin_port = htons(99999);
caddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(sock,(sockaddr*)&caddr, sizeof(caddr)) == SOCKET_ERROR)
{
cout<<"connect failed !"<<endl;
closesocket(sock);
}
else
{
cout<<"connect success !"<<endl;
while (1)
{
string data;
cin>>data;
if (data == "quit")
{
cout<<"结束会话!"<<endl;
break;
}
const char* sendData;
sendData = data.c_str();//string ->const char*
send(sock, sendData, strlen(sendData),0);
char recvData[1024]={0};
int recLen = recv(sock, recvData,sizeof(recvData)-1, 0);
if (strstr(recvData,"quit") != NULL)
{
cout<<"对方已断开连接.."<<endl;
break;
}
if (recLen > 0)
{
cout<<"message from server:"<<recvData<<endl;
}
}
closesocket(sock);
}
WSACleanup();
system("pause");
return 0;
}
4.实现效果