网络通信socket
套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口
计算机是通过TCP/IP协议进行互联从而进行通信的,为将TCP/IP协议进行隐藏,引出套接字这个概念
套接字可以看成【IP地址+端口号】
套接字提供了流套接字与数据报套接字两种组合
- 流套接字基于TCP(stream)
- 数据报套接字基于UDP(datagram)
流程
在Windows环境下进行开发套接字系统
WinSock DLL
注:在使用时一定要包含
#pragma comment(lib,"ws2_32.lib")
int WSAStartup(
WORD wVersionRequested, //调用者能使用的Windows Socket支持的最高版本。高位指定副版本,低位指定主版本号
LPWSADATA lpWSAData //指向WSADATA的指针,用于接收Windows Socket的实现细节
);
//该函数在一个进程中初始化WS2_32.dll的使用
服务器端
#include<WinSock2.h>
#include<iostream>
#include<string>
#include<ctime>
#include<thread>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
void sendMsg(int cli_sock) {
//发送消息
string msg = "<html><head></head><body>Hello World!</body></html>";
string httpHeader = "";
httpHeader += "HTTP/1.1 200 OK\r\n";
httpHeader += "Content-Type:text/html;charset-UTF-8\r\n";
httpHeader += "Content-Length:" + sizeof(msg);
httpHeader += "\r\n";
httpHeader += "\r\n";//消息头与消息之间需要有一个空行
httpHeader += msg;
//httpHeader += "\r\n";
const char *tem = httpHeader.c_str();
int ret = send(cli_sock, tem, sizeof(tem), 0);
if (ret > 0) {
cout << "发送成功!" << endl;
}
else {
cout << "ERROR" << endl;
}
}
int main() {
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data)==-1) {
cout << "初始化错误!" << endl;
WSACleanup();
return -1;
}
SOCKET m_sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8081);
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if (::bind(m_sock, (sockaddr*)&addr, sizeof(addr))==-1) {
cout << "bind error!" << endl;
return -1;
}
if (listen(m_sock, SOMAXCONN)==-1) {
cout << "listen error" << endl;
return -1;
}
cout << "等待客户端连接..." << endl;
sockaddr_in cli_addr;
int len = sizeof(cli_addr);
int cli_sock = accept(m_sock, (sockaddr*)&cli_addr, &len);//阻塞等待客户端的连接
if (cli_sock == -1) {
cout << "accept error";
return -1;
}
cout << "客户端[" << cli_sock << "]已连接" << endl;
//输出收到的信息
char buf[32] = { 0 };
recv(cli_sock, buf, sizeof(buf), 0);
cout << "收到的消息为:" << buf << endl;
sendMsg(cli_sock);
//thread ts(sendMsg, cli_sock);
//ts.detach();
//Sleep(3000);
//WSACleanup();
system("pause");
return 0;
}
客户端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#include<iostream>
#include<string>
#include<ctime>
#include<thread>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
void sendMsg(int cli_sock) {
//发送消息
string msg = "<html><head></head><body>Hello World!</body></html>";
string httpHeader = "";
httpHeader += "HTTP/1.1 200 OK\r\n";
httpHeader += "Content-Type:text/html;charset-UTF-8\r\n";
httpHeader += "Content-Length:" + sizeof(msg);
httpHeader += "\r\n";
httpHeader += "\r\n";//消息头与消息之间需要有一个空行
httpHeader += msg;
//httpHeader += "\r\n";
const char *tem = httpHeader.c_str();
int ret = send(cli_sock, tem, sizeof(tem), 0);
if (ret > 0) {
cout << "发送成功!" << endl;
}
else {
cout << "ERROR" << endl;
}
}
int main() {
//初始化
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data) == -1) {
cout << "初始化错误!" << endl;
WSACleanup();
return -1;
}
//创建套接字
SOCKET m_sock = socket(AF_INET, SOCK_STREAM, 0);
//指定通信的ip和端口
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8081);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//向服务器发起连接请求
if (connect(m_sock, (sockaddr*)&addr, sizeof(addr)) == -1) {
cout << "bind error!" << endl;
return -1;
}
cout << "服务器连接成功..." << endl;
//接收数据
char buf[32] = { 0 };
recv(m_sock, buf, sizeof(buf), 0);
if (buf) {
cout << "收到的消息为:" << buf << endl;
}
//发送数据
sendMsg(m_sock);
//关闭socket连接,释放资源
WSACleanup();
system("pause");
return 0;
}