服务器:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string>
#include<WinSock2.h> //网络库用2.2版本 目前系统的最高版本
#pragma comment(lib,"Ws2_32.lib") //加载动态连接库 x32.x64都是用ws2_32.lib这一个版本
//上面为第二版 第一版头文件为WinSock.h 动态库为wsock32.lib
using namespace std;

int main()
{
/*调用的库版本 如果直接赋值2.1 则出错(WORD为短整型,2.1为浮点型)
用该宏去储存,转到内存MAKEWORD(2,1)为258 转换成2进制为0001 0000 0010
即将主版本号2,存放在低字节位(1个字节占8位),副版本号1,存放在高字节0001 <因为在内存中是小头方式存储 高位数据在前> */
WORD m_versions = MAKEWORD(2,2); //MAKEWORD(A,B)参数1为副版本号,参数2为主版本号
WSADATA m_data;//用于接受返回的socket信息

//***1*** 打开网络库
int answer = WSAStartup(m_versions, &m_data); //解析参数2 1为我们要使用的版本 2为系统能提供的最高版本 3为当前库的信息 4为打开结果 或当前套接字状态

if (answer != 0)//打开失败的结果
{
switch (answer)
{
case WSASYSNOTREADY:
printf("网络通信依赖的网络子系统还没有准备好。");
break;
case WSAVERNOTSUPPORTED:
printf("系统不支持当前所需库版本。");
break;
case WSAEINVAL:
printf("无法找到当前库版本所需DLL。");
break;
case WSAEPROCLIM:
printf("当前端口数量已达限制。");
break;
case WSAEINPROGRESS:
printf("当前初始化函数被阻塞。");
break;
case WSAEFAULT:
printf("当前指针(参数2)为无效指针。");
break;
}
}
if (m_data.wVersion != 514) //即未能打开2.2版本 2.2版本以单字节存储即为十进制的514
{//HIBYTE(m_data.wVersion)获取该成员的高字节(即高版本号) LOBYTE()获取该成员的低字节
WSACleanup(); //未能打开指定版本,则关闭该网络库
system("pause");
return 0;
}

//***2*** 创建服务器socket 每个返回的值都是唯一的 返回的值为TCP/IP协议的总编号,代表着各协议的特点 。
SOCKET m_ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //类似于MFC的窗口句柄,对该端口进行操作都需使用该套接字值
//参数1地址类型(IPV4形式),2套接字类型(顺序,可靠,双向,基于连接的字节流),3协议的类型(TCP协议 与参数1对应)

if (m_ServerSocket == INVALID_SOCKET)//创建失败
{
int m_ErrorNum=WSAGetLastError();
printf("创建服务器socket失败,错误代码:%d\n", m_ErrorNum);
WSACleanup(); //未能打开指定版本,则关闭该网络库
system("pause");
return 0;
}

sockaddr_in m_ServerSocketaddr;//结构体,存储地址类型,地址和端口 (sockaddr_in与sockaddr结构一样,但前者方便赋值,后者方便作为参数传递)
m_ServerSocketaddr.sin_family = AF_INET;//与创建时的地址类型相同
m_ServerSocketaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//将字符串形式转换成IP地址形式存储,127.0.0.1为回环地址,在本地(不出电脑)测试使用
m_ServerSocketaddr.sin_port = htons(12345);//端口号 使用时应将其转换成主机字节顺序,且端口号是唯一的,不能重复绑定

//***3*** 绑定对应的地址(找到电脑)和端口号(找到具体应用)
int m_bind = bind(m_ServerSocket, (sockaddr *)&m_ServerSocketaddr, sizeof(m_ServerSocketaddr));
if (m_bind !=0)//创建失败
{
int m_ErrorNum = WSAGetLastError();
printf("绑定失败,错误代码:%d\n", m_ErrorNum);
closesocket(m_ServerSocket);
WSACleanup();
system("pause");
return 0;
}

//***4*** 启动监听,监听是否有客户端连接(类似启动服务器 让客户端可以进行连接)
int m_listen=listen(m_ServerSocket,5);//服务器的sockt。挂起连接队列最大长度(假设服务器能同时处理5个,现在进来了8个,剩下的进入队列等待处理)SOMAXCONN则让系统自行选择合适个数
if (m_listen != 0)//启动失败
{
int m_ErrorNum = WSAGetLastError();
printf("启动失败,错误代码:%d\n", m_ErrorNum);
closesocket(m_ServerSocket);
WSACleanup();
system("pause");
return 0;
}

sockaddr_in m_ClientSocketaddr;//同步骤3一致,为存放客户端数据的结构体
int m_ClientLen = sizeof(m_ClientSocketaddr);//结构体大小

//***5*** 接受连接。当有客户端连接进来后,服务器为其创建一个socket,用于维持通信.参数2.3也可设置为NULL 不得到客户端的信息
SOCKET m_ClientSocket = accept(m_ServerSocket, (sockaddr *)&m_ClientSocketaddr, &m_ClientLen);
//accept函数会一直处于阻塞状态(等待连接),不会往下执行 且一次只能连一个,多个客户端连接则需要循环,且数量要相对应(否则一直阻塞)

if (m_ClientSocket == INVALID_SOCKET)//返回的为无效socket
{
int m_ErrorNum = WSAGetLastError();
printf("客户端连接失败,错误代码:%d\n", m_ErrorNum);
closesocket(m_ServerSocket);
WSACleanup();
system("pause");
return 0;
}
printf("客户端连接成功\n");

int a = 5;
while (a!=0,a--)
{

//***6***接受客户端发送的数据
char StoCbuf[1500] = { 0 };//用于存储服务器接受客户端发来的字符
int a = sizeof(StoCbuf);
int m_ClientStrLen = recv(m_ClientSocket, StoCbuf, sizeof(StoCbuf), 0); //1接受来自哪的sockt,存放在哪,放多少,读取方式(0为默认) 也会一直处于阻塞状态,直到客户端对其操作
if (m_ClientStrLen == 0)//即客户端已下线
{
printf("连接中断,客户端已下线");
}
else if (m_ClientStrLen == SOCKET_ERROR)
{
int m_ErrorNum = WSAGetLastError();
printf("接受客户端数据失败,错误代码:%d\n", m_ErrorNum);
break;
}
else
{
printf("客户端:%s\n", StoCbuf);
}

//***7***给客户端发送数据
printf("服务器:");
gets(StoCbuf);
int m_ServerStrLen = send(m_ClientSocket, StoCbuf, strlen(StoCbuf), 0);//目的socket,发送的数据,发送数据的长度,发送方式
if (m_ServerStrLen == SOCKET_ERROR)
{
int m_ErrorNum = WSAGetLastError();
printf("服务器发送数据失败,错误代码:%d\n", m_ErrorNum);
}

if (strcmp(StoCbuf, "886") == 0)
{
printf("结束对话\n");
break;
}

//使用完毕后,先销毁创建的套接字(该函数为网络库里面的函数),再关闭网络库
closesocket(m_ServerSocket);
WSACleanup();

system("pause");
}

客户端:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int main()
{
/*1打开网络库*/
WORD m_versions = MAKEWORD(2, 2); //MAKEWORD(A,B)参数1为副版本号,参数2为主版本号
WSADATA m_data;//用于接受返回的socket信息
int answer=WSAStartup(m_versions,&m_data);
if (answer != 0)//打开失败的结果
{
switch (answer)
{
case WSASYSNOTREADY:
printf("网络通信依赖的网络子系统还没有准备好。");
break;
case WSAVERNOTSUPPORTED:
printf("系统不支持当前所需库版本。");
break;
case WSAEINVAL:
printf("无法找到当前库版本所需DLL。");
break;
case WSAEPROCLIM:
printf("当前端口数量已达限制。");
break;
case WSAEINPROGRESS:
printf("当前初始化函数被阻塞。");
break;
case WSAEFAULT:
printf("当前指针(参数2)为无效指针。");
break;
}
return 0;
}
if (m_data.wVersion != 514) //即未能打开2.2版本 2.2版本以单字节存储即为十进制的514
{//HIBYTE(m_data.wVersion)获取该成员的高字节(即高版本号) LOBYTE()获取该成员的低字节
WSACleanup(); //未能打开指定版本,则关闭该网络库
system("pause");
return 0;
}

/*2创建服务器socket*/
SOCKET m_ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //类似于MFC的窗口句柄,对该端口进行操作都需使用该套接字值
//参数1地址类型(IPV4形式),2套接字类型(顺序,可靠,双向,基于连接的字节流),3协议的类型(TCP协议 与参数1对应)

if (m_ServerSocket == INVALID_SOCKET)//创建失败
{
int m_ErrorNum = WSAGetLastError();
printf("创建服务器socket失败,错误代码:%d\n", m_ErrorNum);
WSACleanup(); //未能打开指定版本,则关闭该网络库
system("pause");
return 0;
}

/*3连接到服务器*/
sockaddr_in m_ServerMsg;//装载服务器信息
m_ServerMsg.sin_family = AF_INET;//地址类型
m_ServerMsg.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//服务器IP地址 将字符串形式转换成IP地址形式存储,127.0.0.1为回环地址,在本地(不出电脑)测试使用
m_ServerMsg.sin_port = htons(12345);//服务器的端口号 将网络字节序转换为主机字节序
int m_connect = connect(m_ServerSocket, (sockaddr*)&m_ServerMsg, sizeof(m_ServerMsg));
if (m_connect != 0)
{
int m_ErrorNum = WSAGetLastError();
printf("连接服务器失败,错误代码:%d\n", m_ErrorNum);
closesocket(m_ServerSocket);//关闭创建的socket;
WSACleanup(); //未能打开指定版本,则关闭该网络库
system("pause");
return 0;
}
printf("服务器连接成功\n");

while (1)
{
/*4发送消息给服务器*/
char CtoSbuf[1500] = { 0 };//客户端发送给服务器
printf("客户端:");
gets(CtoSbuf);
int m_ServerStrLen = send(m_ServerSocket, CtoSbuf, strlen(CtoSbuf), 0);//目的socket,发送的数据,发送数据的长度,发送方式
if (m_ServerStrLen == SOCKET_ERROR)
{
int m_ErrorNum = WSAGetLastError();
printf("客户端发送数据失败,错误代码:%d\n", m_ErrorNum);
}

/*5接受服务器发送的数据*/
char StoCbuf[1500] = { 0 };//用于存储服务器发来的字符
int m_ClientStrLen = recv(m_ServerSocket, StoCbuf, sizeof(StoCbuf), 0); //1接受来自哪的sockt,存放在哪,放多少,读取方式(0为默认) 也会一直处于阻塞状态,直到客户端对其操作
if (m_ClientStrLen == 0)//即客户端已下线
{
printf("连接中断,服务器已关闭");
}
else if (m_ClientStrLen == SOCKET_ERROR)
{
int m_ErrorNum = WSAGetLastError();
printf("接受客户端数据失败,错误代码:%d\n", m_ErrorNum);
break;
}
else
{
printf("服务器:%s\n",StoCbuf);
}

if (strcmp(StoCbuf, "886") == 0)
{
printf("结束对话\n");
break;
}

}

closesocket(m_ServerSocket);//关闭创建的socket;
WSACleanup(); //未能打开指定版本,则关闭该网络库
system("pause");
}

先运行服务器,再运行客户端,运行效果如下

socket,实现服务器和客户端对话的更多相关文章

  1. C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法

    C#调用接口注意要点   在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...

  2. Socket通信——服务器和客户端相互通信

    所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求.  Socket和S ...

  3. socket,模拟服务器、客户端通信

    服务器代码: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;u ...

  4. java socket 单服务器多客户端实时通信

    想用JAVA做一个服务器,请问怎么利用TCP和线程,实现多个客户端同时在线,能与服务器进行交互? 服务器监听端口 做个无限循环 接到一个连接就创建一个通道线程,并将通道线程存储到一个list集合中 1 ...

  5. Socket实现服务器与客户端的交互

       连接过程:   根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认. (1)服务器监听:是服务器端套接字并不定位具体的客户端套接 ...

  6. socket模拟服务器,客户端下载东西(ftp)

    服务端(ftp_server.py) import hashlib,socket,os server = socket.socket() server.bind(("localhost&qu ...

  7. Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)

    转载地址:http://blog.csdn.net/mad1989/article/details/9147661 ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当 ...

  8. Linux系统编程(37)—— socket编程之UDP服务器与客户端

    典型的UDP客户端/服务器通讯过程: 编写UDP Client程序的步骤 1.初始化sockaddr_in结构的变量,并赋值.这里使用"8888"作为连接的服务程序的端口,从命令行 ...

  9. python socket之tcp服务器与客户端demo

    python socket之tcp服务器与客户端demo 作者:vpoet mails:vpoet_sir@163.com server: # -*- coding: cp936 -*- ''' 建立 ...

随机推荐

  1. Spring MVC知识梳理

    同上一篇博客,复习梳理SpringMVC知识点,这次的梳理比较快,很多细节没有顾虑到,后期可能会回来补充 1. 整体架构 1.1 在学习了SSM框架后我们来理清三者的应用层面 浏览器发送请求,请求到达 ...

  2. 网站提权之MSF骚操作

    当我们在进行web渗透测试的时候,拿到了webshell,但是在执行net user.whoami.类似的命令会发现怎么好像用不了,没有回显,权限不够,这可怎么办呐? 测试环境: 内网,没钱买服务器, ...

  3. 正式学习MVC 05

    1.剃须刀模板razor的使用 1)混编 循环语法 @model List<MVCStudy.Models.Student> @{ ViewBag.Title = "List&q ...

  4. vue配合iview/element等ui实现界面效果起步

    iview与element都是与vue配合使用的ui框架,用法与配置基本一致,在此,我以iview为例,教你如何起步.*首先,你需要有一定的vue基础,如果你还是个小白,可以去我之前介绍如何搭建一个v ...

  5. 盒马微信小程序

    盒马app刚出现,就吸足了眼球.最近看了看盒马界面,很Q,就想着仿照app写个小程序. 功能介绍 好奇微信小程序是如何制作的,也对盒马app感兴趣,就尝试写了这个盒马小程序.实现了app的部分功能,还 ...

  6. idea创建简单web项目分析Servlet的请求转发与重定向的区别

     注:如需转载,请附上原文链接,如有建议或意见,欢迎批评指正! 需求说明: // index.jsp页面 1 <% 2 String basePath = request.getScheme() ...

  7. 027.掌握Service-Ingress使用

    一 Ingress简介 1.1 Ingress 通常Service的表现形式为IP:Port,即工作在TCP/IP层. 对于基于HTTP的服务来说,不同的URL地址经常对应到不同的后端服务(RS)或者 ...

  8. Java多线程并发01——线程的创建与终止,你会几种方式

    本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...

  9. Java自学路线图之Java基础自学

    自学Java要从Java基础语法开始自学,自学Java的过程中打好基础是很重要的!首先自学:面向对象基础,API基础,集合基础.这些对Java小白的数学和英语能力的要求门槛不高,在学习的过程中积累相应 ...

  10. c++第一周测验

    本次得分为:14.00/14.00, 本次测试的提交时间为:2020-03-08, 如果你认为本次测试成绩不理想,你可以选择再做一次. 1 单选(1分) 下面程序片段哪个没错? 得分/总分 A. in ...