IP:用来区分主机的
ipv4 4个字节来保存 IP地址
指针 指针变量:4个字节来保存内存地址
如:“192.168.0.166” : 4段,每段1个字节,0-255
子网掩码:255.255.255.0
前三段 用来 表示网络号
最后一段 用来 表示哪台主机号
一个操作系统上,通常有65535个端口号
端口的作用是用来区分同一台主机上的不同的应用程序.
一般为了区分,一个程序会占用一个或者多个端口号,其他程序不能抢.
自己写代码时.注意:使用1000左右的端口号就行了.
注意:大小端问题,注意:转换和是否需要转换
#include
#pragma comment(lib,"Ws2_32.lib")
#include
#include
int main()
{
//0. 请求协议版本
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("请求协议版本失败:%d\n", GetLastError);
return -1;
}
printf("请求协议版本成功!\n");
//1. 创建socket
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SOCKET_ERROR == serverSocket)
{
printf("创建socket失败:%d\n", GetLastError);
//8. 清理协议版本信息
WSACleanup();
return -1;
}
printf("创建socket成功!\n");
//2. 服务器协议地址簇
SOCKADDR_IN sAddr = { 0 };
sAddr.sin_family = AF_INET; //和socket第一个参数一致
sAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //把数字格式字符串转换为网络字节序
sAddr.sin_port = htons(10086); //65535 5000以上,大小端转换
//3. 连接服务器
int r = connect(serverSocket, (sockaddr*)&sAddr, sizeof sAddr);
if (-1 == r)
{
printf("连接服务器失败:%d\n", GetLastError);
//7. 关闭socket
closesocket(serverSocket);
WSACleanup();
return -1;
}
printf("连接服务器成功!\n");
//4. 通信
char buff[1024];
while (1)
{
printf("请输入:");
scanf("%s", buff);
send(serverSocket, buff, strlen(buff), NULL);
}
//5. 关闭socket
closesocket(serverSocket);
//6. 清理协议版本信息
WSACleanup();
return 0;
}
服务器端:
#include
#pragma comment(lib,"Ws2_32.lib")
#include
#include
//最多1024个客户端连接 没有管理客户端的socket
SOCKET clientSocket[1024];
int count = 0;
//线程处理函数
void myThreadFunction(void *arg);
int main()
{
//0 请求协议版本
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2) {
printf("请求协议版本失败:%d\n", GetLastError());
return -1;
}
printf("请求协议版本成功!\n");
//1 创建socket
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SOCKET_ERROR == serverSocket) {
printf("创建socket失败:%d\n", GetLastError());
//8 清理协议版本信息
WSACleanup();
return -1;
}
printf("创建socket成功!\n");
//2 服务器协议地址簇
SOCKADDR_IN sAddr = { 0 };
sAddr.sin_family = AF_INET; // 和socket第一个参数一致
sAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 把数点格式字符串转换成网络字节序
sAddr.sin_port = htons(10086); // 65536 5000以上 大小端转换
//3 绑定
int r = bind(serverSocket, (sockaddr*)&sAddr, sizeof sAddr);
if (-1 == r) {
printf("绑定失败:%d\n", GetLastError());
//7 关闭socket
closesocket(serverSocket);
//8 清理协议版本信息
WSACleanup();
return -1;
}
printf("绑定成功!\n");
//4. 监听
r = listen(serverSocket,10);
if (-1 == r)
{
printf("监听失败:%d\n",GetLastError());
//7. 关闭socket
closesocket(serverSocket);
//8. 清理协议版本信息
WSACleanup();
return -1;
}
printf("监听成功!\n");
//5. 等待客户端连接
SOCKADDR_IN cAddr = { 0 };
int len = sizeof cAddr;
for (int i = 0;i < 1024;i++)
{
memset(&cAddr,0,len);
clientSocket[i] = accept(serverSocket,(sockaddr*)&cAddr,&len); //阻塞
if (SOCKET_ERROR == clientSocket[i])
{
printf("客户端连接失败:%d\n",GetLastError());
//7. 关闭socket
closesocket(serverSocket);
//8. 清理协议版本信息
WSACleanup();
return -1;
}
printf("有客户端连接到服务器了:%s,%d!\n",
inet_ntoa(cAddr.sin_addr),ntohl(cAddr.sin_port));
CreateThread(NULL,NULL,
(LPTHREAD_START_ROUTINE)myThreadFunction,
(void*)i,NULL,NULL);
}
//7. 关闭socket
closesocket(serverSocket);
//8. 清理协议版本信息
WSACleanup();
return 0;
}
//线程处理函数
void myThreadFunction(void* arg)
{
int idx = (int)arg;
char buff[1024];
int r;
while (1)
{
r = recv(clientSocket[idx],buff,1023,NULL);
if (r > 0)
{
buff[r] = 0;
printf("客户端%d发来数据:%s\n",idx,buff);
}
}
}
#include "widget.h"
#include "ui_widget.h"
#pragma execution_character_set("GB2312")
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("服务器 ");
//1. 创建QTcpSocket对象
pTcpServer = new QTcpServer(this); //指定父对象,让他可以自动回收内存
pTcpSocket = NULL;
//2. 监听
pTcpServer->listen(QHostAddress::Any,10086);
//3. 等待客户端连接
//3.1. 关联信号与槽
//connect(pTcpServer,QTcpServer::newConnection,this,...)
connect(pTcpServer,&QTcpServer::newConnection,
[=](){
//3.2. 获取客户端socket
pTcpSocket = pTcpServer->nextPendingConnection();
qDebug() << "客户端连接服务器成功" << endl;
//3.3. 获取客户端ip地址和端口号
QString ipStr = pTcpSocket->peerAddress().toString();
quint16 portUint = pTcpSocket->peerPort();
//相当于sprintf
QString buff = QString("客户端ip:%1,客户端端口号:%2").arg(ipStr).arg(portUint);
//3.4. 显示在某个地方 ui.texteditRecv
ui->textEdit_Recv->setText(buff);
//4. 通信
//4.1. 服务器接受客户端数据
connect(pTcpSocket,&QTcpSocket::readyRead,
[=](){
QByteArray data = pTcpSocket->readAll();
ui->textEdit_Recv->append(data);
});
});
}
Widget::~Widget()
{
delete ui;
}
//4.2. 发送数据 服务器 发送到 客户端
void Widget::on_btn_Send_clicked()
{
if(pTcpSocket)
{
QString str = ui->textEdit_Send->toPlainText();
pTcpSocket->write(str.toUtf8().data());
}
}
void Widget::on_btn_Close_clicked()
{
if(pTcpSocket)
{
pTcpSocket->disconnectFromHost();
pTcpSocket->close();
}
}
客户端:
#include "clientwidget.h"
#include "ui_clientwidget.h"
#pragma execution_character_set("GB2312")
clientwidget::clientwidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::clientwidget)
{
ui->setupUi(this);
setWindowTitle("客户端 ");
//1. 创建QTcpSocket对象
pTcpSocket = new QTcpSocket(this);
//2.3. 检查是否连接上了服务器
connect(pTcpSocket,&QTcpSocket::connected,
[=](){
ui->textEdit_Recv->setText("连接服务器成功!");
//3. 通信
//3.1. 客户端接受服务器数据
connect(pTcpSocket,&QTcpSocket::readyRead,
[=](){
QByteArray data = pTcpSocket->readAll();
ui->textEdit_Recv->append(data);
});
});
}
clientwidget::~clientwidget()
{
delete ui;
}
//2. 连接服务器
void clientwidget::on_btn_Connect_clicked()
{
//2.1. 获取用户输入的ip地址和端口号
QString ipStr = ui->lineEdit_IP->text();
quint16 portUint = ui->lineEdit_Port->text().toUInt();
//2.2. 连接服务器
pTcpSocket->connectToHost(ipStr,portUint);
}
//3.2. 客户端 发送数据到 服务器
void clientwidget::on_btn_send_clicked()
{
if(pTcpSocket)
{
QString str = ui->textEdit_Send->toPlainText();
pTcpSocket->write(str.toUtf8().data());
}
}
//4. 断开连接
void clientwidget::on_pushButton_3_clicked()
{
if(pTcpSocket)
{
pTcpSocket->disconnectFromHost();
pTcpSocket->close();
}
}