目录
一、介绍
tcp和udp的区别之一,即tcp是有连接的,udp是无连接的,udp收发数据的代码可以独立运行,tcp发数据前必须确保收数据的一方是打开的,否则无法建立连接。
二、收数据
tcpRecv.h
#pragma once
#include<iostream>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
class tcpRecv
{
public:
tcpRecv();
~tcpRecv();
void initialization();
void recvData();
public:
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
SOCKET s_accept;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
SOCKADDR_IN accept_addr;
};
tcpRecv.cpp
#include "tcpRecv.h"
tcpRecv::tcpRecv()
{
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(14555);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "套接字绑定失败!" << endl;
WSACleanup();
}
else {
cout << "套接字绑定成功!" << endl;
}
//设置套接字为监听状态
if (listen(s_server, SOMAXCONN) < 0) {
cout << "设置监听状态失败!" << endl;
WSACleanup();
}
else {
cout << "设置监听状态成功!" << endl;
}
cout << "服务端正在监听连接,请稍候...." << endl;
//接受连接请求
int len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR *)&accept_addr, &len);
if (s_accept == SOCKET_ERROR) {
cout << "连接失败!" << endl;
WSACleanup();
}
cout << "连接建立,准备接受数据" << endl;
}
tcpRecv::~tcpRecv()
{
//关闭套接字
closesocket(s_server);
closesocket(s_accept);
//释放DLL资源
WSACleanup();
}
void tcpRecv::initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
//填充服务端地址信息
}
void tcpRecv::recvData() {
//接收数据
int recv_len = recv(s_accept, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
}
else {
cout << "接收信息为:" << recv_buf << endl;
}
}
main.cpp
#include "tcpRecv.h"
int main() {
tcpRecv tcp;
while (1) {
tcp.recvData();
}
return 0;
}
三、发数据
tcpSend.h
#pragma once
#include<iostream>
#include<string>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
class tcpSend
{
public:
tcpSend();
~tcpSend();
void initialization();
void sendData(std::string&data);
public:
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
};
tcpSend.cpp
#include "tcpSend.h"
tcpSend::tcpSend()
{
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(14555);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "服务器连接失败!" << endl;
WSACleanup();
}
else {
cout << "服务器连接成功!" << endl;
}
}
tcpSend::~tcpSend()
{
//关闭套接字
closesocket(s_server);
//释放DLL资源
WSACleanup();
}
void tcpSend::initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
//填充服务端地址信息
}
void tcpSend::sendData(std::string&data) {
int send_len = send(s_server, data.c_str(), sizeof(data), 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
}
else {
std::cout << "send data:" << data.c_str() << std::endl;
}
}
main.cpp
#include "tcpSend.h"
int main() {
tcpSend tcp;
for (int i = 0; i < 100; i++) {
std::string s = "test " + std::to_string(i);
tcp.sendData(s);
Sleep(1000);
}
return 0;
}