服务器:

#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. async/await实现图片的串行、并行加载

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 50-Python2和3字符编码的区别

    目录 Python2和3字符编码的区别 python2 python3 Python2和3字符编码的区别 区别点 python2 python3 print 是一个语法结构 是一个函数,print(' ...

  3. swoole(2)swoole进程结构

    一:进程基本概念 系统中正在运行的一个程序,程序一旦运行就是进程 一个进程可以拥有多个线程 核心内容分为两部分:内存(进程创建时从系统分配的,它所创建的变量都会存储在这一块内存中).上下文环境 二:s ...

  4. DotNet Core 使用 StackExchange.Redis 简单封装和实现分布式锁

    前言 公司的项目以前一直使用 CSRedis 这个类库来操作 Redis,最近增加了一些新功能,会存储一些比较大的数据,内测的时候发现其中有两台服务器会莫名的报错 Unexpected respons ...

  5. Day 3 DP

    1. P1015 精卫填海 01背包 + 判断 #include <iostream> using namespace std; , MAXV = ; int v, n, m, f[MAX ...

  6. vue-router03 vue-cli

    1.钩子: next讲解: next()进行路由跳转 next(false)取消路由跳转 beforeRouteEnter (to, from, next) { next(vm => { // ...

  7. JavaScript两道例题

    1.有一个卡车司机肇事后想逃跑,但是被三个人看见其车牌号码,但是没有看全.一号说:车牌的前两位是一样的,二号说:车牌的后两位是一 样的,但是与前两位不一样,三号说:车牌是一个数字的平方,请计算车辆号牌 ...

  8. startUML5.0中的tools下怎么没有java、c等选项

    这也是帮一个直系学妹弄得,哈哈~~~ 具体做法如下: 进入到StartUML\modules目录下,里面有很多文件夹,比如startuml-cpp.startuml-csharp等等, 进入到每个文件 ...

  9. Java反射之成员方法的反射

    上一篇介绍了Java反射之成员变量的反射,这次介绍成员方法的反射. [一]Method类 Method类中封装了所有java方法的属性,包括该方法是否私有,该方法的修饰符,返回值,参数,抛的错误等等. ...

  10. windows git pull或者push代码时弹出安全框解决办法

    目录 1.打开控制面板->凭据管理器>删除已有的git凭证 2.新增一个凭证 @ 如果报如下错误: 1.打开控制面板->凭据管理器>删除已有的git凭证 2.新增一个凭证 网络 ...