Windows环境下TCP通信的服务端和客户端
程序员文章站
2022-06-06 14:10:25
...
服务端
- 建立socket套接字
- 绑定接收端口
bind()
- 监听网络端口
listen()
- 等待接收客户端连接
accept()
- 向客户端发送数据
send()
- 关闭套接字
closesocket()
建立socket套接字
#include <stdio.h>
#include <winsock2.h>
#include <iostream>
#pragma comment(lib."ws2_32.lib">
using namespace std;
int main(int argc, char* argv[])
{
//启动ws2环境
WORD ver = MAKEWORD(2,2);
WSADATA dat;
if(WSAStartup(ver,&dat)!=0)
{
return 0;
}
//建立套接字
SOCKET slisten = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sock == INVALID_SOCKET){
cout<<"套接字建立失败";
return 0;
}
...
}
启动ws2环境
WORD
是微软SDK中的类型,意思为字,是2byte的无符号整数,表示范围0~65535MAKEWORD
是将两个btye型合并成一个WORD
型,而在socket编程中,MAKEWORD(2,2)
表示调用2.2版本,具体可见WSAStartup
(
In WORD wVersionRequested,
Out LPWSADATA lpWSAData // 指向WSADATA类型数据的指针类型
);
建立套接字
AF_INET (协议簇 —— TCP/IP-IPv4)
SOCK_STREAM (TCP流)
这部分可以分别参考这个和这个
绑定接收端口 bind()
socketaddr_in sin = {}; // socketaddr_in是一个结构体类型 所以 = {}; 具体可以在vs2019按F12查看
sin.sin_family = AF_INET; // 协议
sin.sin_port = htons(8888); // 端口号
sin.sin_addr.S_un.S_addr = INADDR_ANY; //任意地址访问 // inet_addr("127.0.0.1"); 本机访问
if(bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) {
cout<<"bind error";
}
前面提到
LPWSADATA
是指向WSADATA
类型数据的指针类型
这里出现一个类似的LPSOCKADDR
,可以用sockaddr*
替换
监听网络端口 listen()
if(listen(slisten,5) == SOCKET_ERROR){
cout<<"Listen error";
}
listen(
In SOCKET s,
In int backlog
);
backlog,积压的工作,表示内核监听队列的最大长度,一般值为5,但随着软硬件的提升,这个参数大小无所谓了
当这个5
起作用时,客户端连接服务器,排队等待,队伍长度超过5后,客户端会受到ECONNECTREFUSE之类的错误
等待接收客户端连接 accept()
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
while(true){
cout<<"等待连接中...";
sClient = accept(slisten,(SOCKADDR*)&remoteAddr,&nAddrlen);
if(sClient == INVALID_SOCKET){
cout<<"accept error";
continue;
}
cout<<"接收到一个连接:"<<inet_ntoa(remoteAddr.sin_addr);
//接收数据
int ret = recv(sClient,revData,255,0);
if(ret > 0){
revData[ret] = 0x00;
cout<<revData;
}
//发送数据
const char* sendData = "Hello,TCPClient";
send(sClient,sendData,strlen(sendData),0);
closesocket(sClient);
}
inet_ntoa
在vs2019可能报错,百度就行
关闭套接字 closesocket()
closesocket(slisten);
WSACleanup();
return 0;
server.cpp
#include <stdio.h>
#include <winsock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
int main(int argc, char* argv[]) {
// 初始化ws2
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) //LPWSADATA 指向WSADATA类型的指针
{
return 0;
}
//建立套接字
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
cout << "socket error";
return 0;
}
//绑定ip和端口
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(sock, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) {
cout << "bind error";
}
//监听
if (listen(sock, 5) == SOCKET_ERROR) {
cout << "Listen error";
}
//循环接受数据
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
while (true) {
cout << "等待连接中...";
sClient = accept(sock, (SOCKADDR*)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET) {
cout << "accept error";
continue;
}
printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
//接受数据
int ret = recv(sClient, revData, 255, 0);
if (ret > 0) {
revData[ret] = 0x00;
cout << revData;
}
//发送数据
const char* sendData = "Hello,TCPClient";
send(sClient, sendData, strlen(sendData), 0);
closesocket(sClient);
}
closesocket(sock);
WSACleanup();
return 0;
}
客户端
- 建立套接字
socket
- 连接服务器
connect()
- 和服务器通信
send()/recv()
- 关闭套接字,关闭加载的套接字库
WSACleanup()
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
#pragma comment(lib,"ws2_32.lib");
using namespace std;
int main()
{
//开启ws2环境
WORD ver = MAKEWORD(2,2);
WSADATA dat;
if(WSAStartup(ver,&dat) != 0){
return 0;
}
//建立套接字socket
while(true){
SOCKET client = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(client == INVALID_SOCKET){
cout<<"invalid socket!";
continue;
}
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.S_un.S_addr = inet_addr("192.168.20.56"); // 对于服务器在本机的,IP还可以用127.0.0.1
if(connect(client, (LPSOCKADDR)&servAddr, sizeof(servAddr) == SOCKET_ERROR){
cout<<"connect error";
closesocket(client);
return 0;
}
// 给服务器发送消息
string data;
cin>>data;
const char* sendData;
sendData = data.c_str();
send(client,sendData,strlen(sendData),0);
// 接收来自服务器的回信
char recData[255];
int ret = recv(client,recData,255,0);
if(ret>0){
recData[ret] = 0x00;
cout<<recData;
}
closesocket(client);
}
WSACleanup();
return 0;
}
send()
这部分用到了一个函数
c_str()
,这个函数返回常量_Elem指针类型,即const _Elem* c_str()
推荐阅读
-
Windows系统下使用flup搭建Nginx和Python环境的方法
-
C#基于TCP协议的服务器端和客户端通信编程的基础教程
-
windows环境下mysql的解压安装及备份和还原
-
Jira7.10.1在Windows环境下的安装和配置教程图解
-
Windows系统下使用flup搭建Nginx和Python环境的方法
-
mycat在windows环境下的安装和启动
-
Win2008 R2 64Bit下IIS环境安装memcache和memcached服务端的方法
-
WIN7下ORACLE10g服务端和客户端的安装图文教程
-
Windows环境下写Linux sh脚本的一次挖坑和填坑
-
ubuntu环境下实现 多线程的socket(tcp) 通信