服务器:

#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. NumPy的随机函数子库——numpy.random

    NumPy的随机函数子库numpy.random 导入模块:import numpy as np 1.numpy.random.rand(d0,d1,...,dn) 生成一个shape为(d0,d1, ...

  2. SpringBoot入门系列(四)整合模板引擎Thymeleaf

    前面介绍了Spring Boot的优点,然后介绍了如何快速创建Spring Boot 项目.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/ ...

  3. disruptor 链路实战 三

    一.创建Event类 Trade import java.util.concurrent.atomic.AtomicInteger; public class Trade { private Stri ...

  4. 无损卡尔曼滤波UKF(3)-预测-生成Sigma点

    无损卡尔曼滤波UKF(3)-预测-生成Sigma点 1 选择创建Sigma点 A 根据 已知上一个时间戳迭代出来的 后验状态 x_{k|k} 和后验协方差矩阵 P_{k|k} 他们代表当前状态的分布. ...

  5. JavaMail(二):利用JavaMail发送复杂邮件

    上一篇文章我们学习了利用JavaMail发送简单邮件,这篇文章我们利用JavaMail发送稍微复杂一点的邮件(包含文本.图片.附件).这里只贴出核心代码,其余代码可参考JavaMail(一):利用Ja ...

  6. 【Python】Pyinstall打包不同尺寸ico制作

    前言 最近工作之余在学习python,用Pyinstall打包exe的时候发现图标只能在任务栏或者大图的情况下出现,其他情况还是默认图标,,,!!!∑(゚Д゚ノ)ノ 分析 查资料是因为exe在不同情况 ...

  7. 原生Canvas循环滚动弹幕(现金红包活动带头像弹幕)

    效果 gif有些糊,可以 在线预览 实现关键点 requestAnimationFrame 循环帧: 绘制单条弹幕,画框子 -> 画头像 -> 写黑色的字 -> 写红色的字, mea ...

  8. Openstack计算Nova组件

    欢迎来到虚拟机的世界,如果我们将Openstack环境里运行在各个无力节点上的各种服务看座生命体,而不是死的指令集合,那么就是一个虚拟机的世界. Openstack的计算组件,也就是Nova项目实现了 ...

  9. 【2020-03-21】Dubbo本地环境搭建-实现服务注册和消费

    前言 本周主题:加班工作.本周内忙于CRUD不能自拔,基本每天都是九点半下班,下周上线,明天还要加班推进进度.今天是休息日,于是重拾起了dubbo,打算近期深入了解一下其使用和原理.之所以说是重拾,是 ...

  10. EF Core-1

    带着问题去思考,大家好! 前几天了解到EF Core的开发模式:DB First(数据库优先),Model First(模式优先),Code First(代码优先). 我所接触的大多是DB First ...