socket,实现服务器和客户端对话
服务器:
#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,实现服务器和客户端对话的更多相关文章
- C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法
C#调用接口注意要点 在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...
- Socket通信——服务器和客户端相互通信
所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. Socket和S ...
- socket,模拟服务器、客户端通信
服务器代码: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;u ...
- java socket 单服务器多客户端实时通信
想用JAVA做一个服务器,请问怎么利用TCP和线程,实现多个客户端同时在线,能与服务器进行交互? 服务器监听端口 做个无限循环 接到一个连接就创建一个通道线程,并将通道线程存储到一个list集合中 1 ...
- Socket实现服务器与客户端的交互
连接过程: 根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认. (1)服务器监听:是服务器端套接字并不定位具体的客户端套接 ...
- socket模拟服务器,客户端下载东西(ftp)
服务端(ftp_server.py) import hashlib,socket,os server = socket.socket() server.bind(("localhost&qu ...
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
转载地址:http://blog.csdn.net/mad1989/article/details/9147661 ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当 ...
- Linux系统编程(37)—— socket编程之UDP服务器与客户端
典型的UDP客户端/服务器通讯过程: 编写UDP Client程序的步骤 1.初始化sockaddr_in结构的变量,并赋值.这里使用"8888"作为连接的服务程序的端口,从命令行 ...
- python socket之tcp服务器与客户端demo
python socket之tcp服务器与客户端demo 作者:vpoet mails:vpoet_sir@163.com server: # -*- coding: cp936 -*- ''' 建立 ...
随机推荐
- hadoop地址配置、内存配置、守护进程设置、环境设置
1.1 hadoop配置 hadoop配置文件在安装包的etc/hadoop目录下,但是为了方便升级,配置不被覆盖一般放在其他地方,并用环境变量HADOOP_CONF_DIR指定目录. 1.1.1 ...
- .ArrayList是如何实现的,ArrayList和LinkedList的区别?ArrayList如何实现扩容?
ArrayList比较简单,主要是通过数组来实现的 需要注意的是其初始容量是10 /** * Default initial capacity. */ private static final int ...
- this软拷贝详解
<script> if( !Function.prototype.softBind ){ Function.prototype.softBind = function( obj ){ va ...
- checkbox,radio自定义美化表单
原理 利用label标签,包裹input的时候,点击label等同于点击input,再用背景图片显示选中和取消选中状态 效果 图片 复选 <!DOCTYPE html> <html& ...
- http相关知识点回顾
一.概述 1.什么是HTTP HTTP是一种可以获取HTML这样的网络资源的一种通讯协议protocol.是在WEB上进行数据交换的基础,是一种客户端--服务器协议.HTTP是一种可扩展的应用层协议, ...
- python读入写入中文名图片
import os import cv2 import numpy as np # 读入中文命名图片 def cv_imread(in_path): cv_img = cv2.imdecode(np. ...
- NetAnalyzer笔记 之 十一 打造自己的协议分析语言(1)初衷与语法构想
回头看看NetAnalyzer开发系文档上次一篇竟然是2016年,老脸一红.不过这几年墨云成功过的讨到一个温柔贤淑的老婆,有了一个幸福的家庭,去年9月又有了一个大胖儿子,想想也就释然了^_^ 其实这几 ...
- 3DGIS与BIM集成集成技术及铁路桥梁可视化系统
3DGIS与BIM的集成技术 3DGIS与BIM的集成技术包括2部分:一是将Revit软件生成的BIM针对3DGIS的快速无损格式转换,这种转换包括几何信息(如形状.位置等信息)和属性信息(如建筑信息 ...
- 基于GIS空间分析的多边形提取技术
现有基于矢量图形的骨架线提取方法主要包括数据预处理.基于约束 Delauny 三角剖分的骨架线结点生成和骨架线的连接 3 个过程,上述过程都可利用现有 GIS 系统的数据处理.空间分析和建模功能实现. ...
- 开篇词The Start以及[Vjudge][HDU2242]空调教室
开篇 这是我写的第一篇记录好题的博客,也是博客园上我发布的第一篇博客. 以后我的所有博客都将在洛谷和博客园上同时发布,同志们有兴趣的在哪里都可以看一看. [https://www.luogu.com. ...