服务端:
#include <iostream>
#include <thread>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main() {
//不用管这两行,抄就完事了
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);
/*
int family : 协议簇,可选AF_INET/AF_INET6/......
int type : 流类型, 可行 SOCK_STREAM/SOCK_DGRAM/SOCKET_RAW...
int protocol: 给0表示由系统自动根据前两个参数选择协议
成功返回描述符
失败返回-1
*/
int server = socket(AF_INET, SOCK_STREAM, 0);
if (server == -1) {
cout << "创建套接字失败:" << errno << endl;
exit(0);
}
/*
AF_INET 的地址类型:
s_addr 表示一个32位地址,可用inet_addr(...)将将字符串转成uint32
htons 表示转变字节序
*/
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_port = htons(8080);
/*
int fd
sockaddr* addr : 表示绑定的端口和本机ip,不设置则由系统随机决定
socklen_t len : 表示结构体的大小
成功返回0
失败返回-1
*/
int bindRet = bind(server, (sockaddr*)&addr, sizeof(addr));
if (bindRet == -1) {
cout << "绑定端口失败:" << errno << endl;
exit(0);
}
/*
int fd
int backlog : 等待连接的客户数量
成功返回0
失败返回-1
*/
int lisRet = listen(server, 100);
if (lisRet == -1) {
cout << "监听失败:" << errno << endl;
exit(0);
}
cout << "服务已经开启,正在8080端口监听..." << endl;
int addr_size = 666; //不能为0
while (true) {
/*
int fd
sockaddr* addr
socklen_t len
成功返回一个新的fd,代表一个与客户端的连接
失败返回-1
*/
int client = accept(server, (sockaddr*)& addr, &addr_size);
if (client == -1) {
cout << "接收客户异常:" << errno << endl;
break;
}
/*这是c++ 11的新特性: 线程 + 匿名函数*/
thread t([](sockaddr_in addr, int client) {
cout << (addr.sin_addr.S_un.S_addr) << ":" << addr.sin_port << endl;
/*
int fd
char* buf,
size_t len,
int flag : 一般设为0
成功,返回接收的字节数,可能部分成功
对方已关闭,返回0
失败,返回-1
*/
char buf[100];
int reRet = recv(client, buf, sizeof(buf), 0);
if (reRet == -1) {
cout << "接收失败:" << errno << endl;
}
cout << "收到:" << buf << endl;
strcpy(buf, "你好客户端");
/*
int fd
const char* buf
int len
int flag : 一般设为0
成功返回发送的字节数,可能部分成功
失败返回-1
*/
int seRet = send(client, buf, sizeof(buf), 0);
if (seRet == -1) {
cout << "发送失败:" << errno << endl;
}
}, addr, client);
t.detach();
}
cout << "服务退出" << errno << endl;
}
客户端:
#include<iostream>
#include<WINSOCK2.H>
#include<STDIO.H>
#include<cstring>
#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
using namespace std;
int main()
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)
{
return 0;
}
while (true) {
SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sclient == INVALID_SOCKET)
{
printf("invalid socket!");
return 0;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &serAddr.sin_addr.S_un.S_addr);
if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{ //连接失败
printf("connect error !");
closesocket(sclient);
return 0;
}
char data[1024];
cin >> data;
const char * sendData;
sendData = data; //string转const char*
//char * sendData = "你好,TCP服务端,我是客户端\n";
send(sclient, sendData, strlen(sendData), 0);
//send()用来将数据由指定的socket传给对方主机
//int send(int s, const void * msg, int len, unsigned int flags)
//s为已建立好连接的socket,msg指向数据内容,len则为数据长度,参数flags一般设0
//成功则返回实际传送出去的字符数,失败返回-1,错误原因存于error
char recData[255];
int ret = recv(sclient, recData, 255, 0);
if (ret > 0) {
recData[ret] = 0x00;
printf(recData);
}
closesocket(sclient);
}
WSACleanup();
return 0;
}