废话不多说,直接进入正题。
首先,导入头文件:
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
注意,如果你使用的是dev-c++,则需要进行如下操作:
进入工具-编译选项,在编辑器下面一栏中加入“-lwsock32”,运行才不会报错。
首先了解,服务端和客户端的交互过程大致如下:
接下来的问题会在代码中一步步解释:
首先,为了方便,我们定义几个函数,存在mysocket.h头文件中(自己创建,命名随意,后面include的时候改过来就可以)
注意,头文件一定要放在和源文件同样的目录下,导入时把尖括号改成双引号
//mysocket.h
#ifndef __MYSOCKET_H__
#define __MYSOCKET_H__
//头文件保护
#include<bits/stdc++.h>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
WSADATA wsdata;
void startup(){
//异步启动
if (WSAStartup(MAKEWORD(2, 2), &wsdata))
/* ^ ^
版本号,这里用的是2.2 |
数据存放处,这里设成全局变量
*/
{
//返回0则成功,否则失败,报错
cout << "启动失败!\n";
WSACleanup();
exit(0);
}
}
SOCKET createSocket(int af, int type){
/*原函数原型:
SOCKET socket(int af, int type, int protocol)
^ ^ ^
协议 类型(后文) 形式(一般用0)
*/
SOCKET ret = socket(af, type, 0);
if (ret == INVALID_SOCKET) //错误返回INVALID_SOCKET
{
//报错
cout << "创建套接字失败!\n";
WSACleanup();
exit(0);
}
return ret;
}
void mysend(SOCKET s, const char* buf){
/*
带报错的send()函数,原函数原型为 :
int send(SOCKET s, const char* buf, int len, int flag)
这里为了简化,省略后两个参数。
函数把buf发送给s,返回发送长度
*/
int len = send(s, buf, sizeof(buf), 0);
if(len < 0) //发送错误
{
cout << "信息发送失败!\n";
WSACleanup();
exit(0);
}
}
void myrecv(SOCKET s, char* buf){
/*
带报错的recv()函数,其原型为:
int recv(SOCKET s, char* buf, int len, int flag)
同样省略后两个参数
函数将从s收到的信息储存在buf中,返回接收长度
*/
int len = recv(s, buf, sizeof(buf), 0);
if(len < 0)
{
cout << "信息接收失败!\n";
WSACleanup();
exit(0);
}
}
#endif
//别忘了
//服务端(以C++作范例)
#include"mysocket.h"
//导入头文件:由于mysock头文件本身就有其它文件,这里无需导入
using namespace std;
SOCKET s_accept;
int main()
{
cout << "---------------------------服务端---------------------------\n";
cout << "正在启动...\n";
startup();
cout << "启动成功!\n";
SOCKET s = createSocket(PF_INET, SOCK_STREAM);
//以IPV6协议创建套接字
//填充信息
SOCKADDR_IN server_addr;
server_addr.sin_family = AF_INET;//协议
server_addr.sin_port = htons(8226);//端口,随便填
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//ip地址,这里填服务端设备上的ip,127.0.0.1是本地ip,不能实现跨设备交互
if (bind(s, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
//绑定套接字
{
cout << "套接字绑定失败!\n";
WSACleanup();
return FALSE;
}
cout << "套接字绑定成功!" << endl;
if (listen(s, 1) == SOCKET_ERROR)
{
//监听:将服务端转为被动状态,接收请求
cout << "监听失败!\n";
WSACleanup();
return FALSE;
}
cout << "设置监听状态成功!\n";
sockaddr_in accept_addr; //用来记录请求连接的套接字信息
int len = sizeof(SOCKADDR);
cout << "等待客户端发起请求..." << endl;
SOCKET t = accept(s, (SOCKADDR*)&accept_addr, &len);
//接受连接请求
if (s_accept == SOCKET_ERROR) {
cout << "请求错误!\n";
WSACleanup();
return FALSE;
}
cout << "建立连接成功!\n";
char recv_buf[1145], send_buf[4514];
while(1){
//信息交互部分,可以作改动
myrecv(t, recv_buf);
cout << "接收到客户端信息:" << recv_buf << endl;
cout << "请输入要发送的信息:";
cin >> send_buf;
mysend(t, send_buf);
}
return 0;
}
//客户端
#include"mysocket.h"
//头文件
using namespace std;
int main()
{
cout << "-----------------客户端----------------\n";
startup(); //启动
//检测版本号
if (LOBYTE(wsdata.wVersion) != 2 || HIBYTE(wsdata.wHighVersion) != 2) {
cout << "版本号与服务端不匹配!" << endl;
WSACleanup();
return FALSE;
}
//填充服务端信息:这里填和服务端一样的就好,不做解释
SOCKET client = createSocket(PF_INET, SOCK_STREAM);
SOCKADDR_IN server_addr;
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(8226);
//发送连接请求 请求连接服务器
if (connect(client, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "连接错误!" << endl;
WSACleanup();
return -1;
}
cout << "成功连接到服务器" << endl;
char send_buf[1145], recv_buf[4514];
while(1){
cout << "输入要发送的信息:";
cin >> send_buf;
mysend(client, send_buf);
cout << "等待服务端响应...\n";
myrecv(client, recv_buf);
cout << "收到来自服务端的信息:" << recv_buf << endl;
}
return 0;
}
最后,如果您觉得这篇文章还不错的话,麻烦点个关注点个赞,这是免费的,您可以随时撤销,您的支持是作者最大的动力!