首先我们知道TCP有客户端和服务器两个部分组成,所以我们在写程序的时候也是分为两个程序的。
我们本章将编写一个最简单的TCP。最简单是指只能够完成收发(不添加线程,定时器等等。这些我会在后面的文章再写)。
我先把完整的代码粘在这里
服务器:
// Server+.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
// Server5.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<iostream>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization();
int main() {
//定义服务端套接字,接受请求套接字
SOCKET s_server;
SOCKET s_accept;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
SOCKADDR_IN accept_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //括号里面放的是客户端的IP地址,由于在本机上所以我们统一使用127.0.0.1
server_addr.sin_port = htons(12500);//括号里面放的是端口号,只要客户端和服务器端的端口号相同就可以
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0); //初学者可以把套接字理解为建立连接的桥梁
//定义长度变量,这些是后面发送接收用到的
int send_len = 0;
int recv_len = 0;
int len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[10];
char recv_buf[10];
//下面主要是做一些判断。判断是否成功绑定套接字,是否处于监听状态,连接是否成功。
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;
//接受连接请求
len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
if (s_accept == SOCKET_ERROR) {
cout << "连接失败!" << endl;
WSACleanup();
return 0;
}
cout << "连接建立,准备接受数据" << endl;
//接收数据
//下面就是收发消息的环节
while (1) {
//接收消息
recv_len = recv(s_accept, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
break;
}
//发送消息
else {
cout << "客户端信息:" << recv_buf << endl;
}
cout << "请输入回复信息:";
cin >> send_buf;
send_len = send(s_accept, send_buf, 100, 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
//关闭套接字
//closesocket(s_server);
// closesocket(s_accept);
//释放DLL资源
// WSACleanup();
return 0;
}
void 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;
}
//填充服务端地址信息
}
客户端
#include<iostream>
#include <thread>
#include<iostream>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization();
int main()
{
//定义长度变量
int send_len = 0;
int recv_len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //IP地址
server_addr.sin_port = htons(12500);//端口
//创建套接字
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;
}
//发送,接收数据
while (1)
{
cout << "请输入发送信息:";
cin >> send_buf;
send_len = send(s_server, send_buf, 100, 0);
if (send_len < 0)
{
cout << "发送失败!" << endl;
}
recv_len = recv(s_server, recv_buf, 100, 0);
if (recv_len < 0)
{
cout << "接受失败!" << endl;
}
else
{
cout << "服务端信息:" << recv_buf << endl;
}
cout << "连接建立,准备接受数据" << endl;
//接收数据
cout << "请输入发送信息:";
cin >> send_buf;
send_len = send(s_server, send_buf, 100, 0);
if (send_len < 0)
{
cout << "发送失败!" << endl;
}
recv_len = recv(s_server, recv_buf, 100, 0);
if (recv_len < 0)
{
cout << "接受失败!" << endl;
}
else
{
cout << "服务端信息:" << recv_buf << endl;
}
}
return 0;
}
void 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;
}
//填充服务端地址信息
}
以上是本章的代码,详细讲解都在后面的注释中。