一、阻塞模式套接字服务端和客户端的运行流程如下:

1.1 服务器运行过程如下:

1.服务器启动后,等待客户端的连接请求。
2.当收到客户端的请求后,在界面上显示该客户端的IP地址和端口,以及“Hello,Server!”问候语。
3.服务器向该客户端应答“Hello,Clinet!”问候语。
4.服务器退出。
1.2客户端运行过程如下:
1.客户端启动后,向服务器发起连接请求。
2.当连接请求被接受后,客户端向服务器发送“Hello,Server!”问候语。
3.等待服务器的应答。
4.当客户端收到服务器的“Hello,Clinet!”应答后,客户端退出。

1.3 客户端和服务器端工作流程如下:

二、实例

2.1 服务器端:Server.cpp

 #include<iostream>
#include<winsock2.h>
#include<string>
#pragma comment(lib,"ws2_32.lib")
using namespace std; #define SERVER_EXIT_OK 0
#define SERVER_DLL_ERROR 1
#define SERVER_API_ERROR 2
#define SERVERPORT 8888
#define MAX_NUM_BUF 64 //全局变量
char bufRecv[MAX_NUM_BUF];//读缓冲区
char bufSend[MAX_NUM_BUF];//写缓冲区
SOCKET sServer;//服务器监听套接字
SOCKET sClient;//接受客户端套接字
bool bConning;//与客户端的连接状态变量 //函数
void InitMember(void);
void ShowSocketMsg(char* str);
int HandleSocketError(char* str);
BOOL RecvLine(SOCKET s, char *buf);//读取一行数据
BOOL SendLine(SOCKET s,char * buf);//发送一行数据
int ExitClient(int nExit);//退出程序 int main(int argc,char*argv[])
{
//调用初始化函数,进行相关初始化工作
InitMember();
//Windows Sockets动态库初始化
WORD wVersionRequseted;
WSADATA wsaData;
int retVal;
wVersionRequseted = MAKEWORD(,);
retVal = WSAStartup(wVersionRequseted,&wsaData);
if (retVal!=)
{
ShowSocketMsg("初始化动态连接库失败");
return SERVER_DLL_ERROR;
}
//确保Winsock dll支持2.2
if (LOBYTE(wsaData.wVersion)!=||HIBYTE(wsaData.wVersion!=))
{
ShowSocketMsg("没有发现动态链接库");
return SERVER_DLL_ERROR;
}
//创建套接字
sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET==sServer)
{
return HandleSocketError("Faild socket()!");
}
//服务器套接字地址
SOCKADDR_IN addrServer;
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(SERVERPORT);
addrServer.sin_addr.S_un.S_addr = INADDR_ANY;
//绑定套接字
retVal = bind(sServer,(sockaddr*)&addrServer,sizeof(addrServer));
if (SOCKET_ERROR==retVal)
{
closesocket(sServer);
return HandleSocketError("绑定套接字失败");
}
//监听
retVal = listen(sServer,);
if (SOCKET_ERROR==retVal)
{
closesocket(sServer);
return HandleSocketError("监听失败");
}
cout << "服务器开始初始化成功!" << endl;
cout << "等待客户端的连接...." << endl;
//接受客户端的请求
sockaddr_in addrClient;
int addrClientLen = sizeof(addrClient);
sClient = accept(sServer,(sockaddr*)&addrClient,&addrClientLen);
if (SOCKET_ERROR==sClient)
{
closesocket(sServer);
return HandleSocketError("接受客户端请求失败");
}
//显示客户端的IP和端口
char *pClientIP = inet_ntoa(addrClient.sin_addr);
u_short clientPort = ntohs(addrClient.sin_port);
cout << "接受到来自客户端的请求:" << endl;
cout << "客户端的IP:" << pClientIP << endl;
cout << "客户端的端口:" << clientPort << endl;
//接受客户端的数据
if (!RecvLine(sClient,bufRecv))
{
return ExitClient(SERVER_API_ERROR);
}
//显示客户端的数据
cout << bufRecv << endl;
//向客户端发送数据
strcpy(bufSend,"hello,client!\n");
if (!SendLine(sClient,bufSend))
{
return ExitClient(SERVER_API_ERROR);
}
//显示退出信息
cout << "服务器正在退出>>>>>" << endl;
//退出
return ExitClient(SERVER_EXIT_OK);
getchar();
return ;
} //初始化成员变量
void InitMember(void)
{
//初始化缓冲区
memset(bufRecv, , MAX_NUM_BUF);
memset(bufSend, , MAX_NUM_BUF);
//初始化
sServer = INVALID_SOCKET;
sClient = INVALID_SOCKET;
//无连接状态
bConning = FALSE; }
void ShowSocketMsg(char* str)
{
MessageBox(NULL,(LPCWSTR)str,(LPCWSTR)"SERVER_ERROR",MB_OK);
} int HandleSocketError(char * str)
{
ShowSocketMsg(str);//显示错误
WSACleanup();//卸载Windows socket DLL
return SERVER_API_ERROR;//退出应用程序
} BOOL RecvLine(SOCKET s, char * buf)
{
BOOL retVal=TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = ; //读入字节数
int nDataLen = ; //数据长度
while (!bLineEnd&&bConning) //与客户端连接,没有换行
{
nReadLen = recv(s,buf+nDataLen,,);
//错误处理
if (SOCKET_ERROR==nReadLen)
{
int nErrorCode = WSAGetLastError();
if (WSAENOTCONN==nErrorCode)
{
ShowSocketMsg("套接字未连接");
}
else if (WSAESHUTDOWN==nErrorCode)
{
ShowSocketMsg("套接字已经关闭");
}
else if (WSAETIMEDOUT == nErrorCode)
{
ShowSocketMsg("连接已断开!");
}
else if (WSAECONNRESET == nErrorCode)
{
ShowSocketMsg("一个现存的远程主机上运行的客户端被强制关闭!");
}
else {} retVal = FALSE; //读数据失败
break;
} if (nReadLen==)//客户端关闭
{
retVal = FALSE;
break;
}
//读入数据
if (*(buf+nDataLen)=='\n')
{
bLineEnd = TRUE;//接受数据结束
}
else
{
nDataLen += nReadLen;//增加数据长度
}
} return retVal;
} BOOL SendLine(SOCKET s, char * buf)
{
int retVal=;//返回值
retVal = send(s, buf, strlen(buf), );//一次发送
//错误处理
if (SOCKET_ERROR == retVal)
{
int nErrCode = WSAGetLastError();//错误代码
if (WSAENOTCONN == nErrCode)
{
ShowSocketMsg("套接字未连接"); }
else if (WSAESHUTDOWN == nErrCode)
{
ShowSocketMsg("套接字已关闭!"); }
else if (WSAETIMEDOUT == nErrCode)
{
ShowSocketMsg("连接已断开!");
}
else {} return FALSE; //发送失败
} return TRUE;
} int ExitClient(int nExit)
{
closesocket(sServer); //关闭监听套接字
closesocket(sClient); //关闭连接客户端套接接
WSACleanup(); //卸载Windows sockets DLL 清理内存
return nExit; //退出
}

2.2 客户端:Client.cpp

 #include <windows.h>
#include <winsock.h>
#include <iostream>
#pragma comment(lib, "wsock32.lib")
using namespace std; #define CLIENT_EXIT_OK 0 //客户端正常退出
#define CLIENT_DLL_REEOR 1 //调用Windows socket dll失败
#define CLIENT_API_ERROR 2 //调用Windows socket api失败
#define MAX_NUM_BUF 64 //缓冲区的最大长度
#define SERVERPORT 8888//服务器TCP端口 //变量
char bufRecv[MAX_NUM_BUF]; //读缓冲区
char bufSend[MAX_NUM_BUF]; //写缓冲区
SOCKET sHost; //socket
BOOL bConning; //连接服务器状态 //函数
void InitMember(void); //初始化变量
int ExitClient(int nExit); //退出
BOOL RecvLine(SOCKET s, char* buf); //读取一行数据
void ShowErrorMsg(void); //显示错误信息 //主函数
int main()
{ //初始化变量
InitMember(); WORD wVersionRequested; //应用程序需要Windows sockets DLL的版本
WSADATA wsaData; //Windows sockets DLL版本信息
int retVal=; //调用Windows sockets API返回值 //初始化Windows Sockets DLL
wVersionRequested = MAKEWORD(, );
retVal = WSAStartup(wVersionRequested, (LPWSADATA)&wsaData);
if ( != retVal)
{
MessageBox(NULL, (LPCWSTR)"初始化动态链接库失败!",(LPCWSTR) "ERROR", MB_OK);
return CLIENT_DLL_REEOR;
} //创建Windows socket
sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sHost)
{
ShowErrorMsg(); //显示错误信息
WSACleanup(); //释放资源
return CLIENT_API_ERROR;//退出
} //准备连接服务器
cout << "客户端初始化成功!" << endl;
cout << "准备连接到服务器..." << endl; //获取主机的信息
LPHOSTENT hostEntry;
char hostname[MAX_NUM_BUF];
gethostname(hostname, MAX_NUM_BUF); //获取主机名称
hostEntry = gethostbyname(hostname); //获取主机信息
if (!hostEntry)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
//设置sockaddr_in
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
addrServ.sin_port = htons(SERVERPORT);
//连接服务器
retVal = connect(sHost, (sockaddr*)&addrServ, sizeof(addrServ));
if (SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
else {
bConning = TRUE; //连接服务器成功
}
//连接服务器成功
cout << "连接服务器成功!" << endl; //向服务器发送数据
strcpy_s(bufSend, "Hello,Server!\n");
retVal = send(sHost, bufSend, strlen(bufSend), );
if (SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
} //从服务器接收数据
if (!RecvLine(sHost, bufRecv))
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
//显示服务器的应答
cout << bufRecv << endl; //退出
return ExitClient(CLIENT_EXIT_OK);
} /*
* 显示错误信息
*/
void ShowErrorMsg(void)
{
int nErrCode = WSAGetLastError();//获取错误代码 HLOCAL hlocal = NULL; //获取错误的文本字符串
BOOL fOk = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, nErrCode, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(PTSTR)&hlocal, , NULL); //显示错误信息
if (hlocal != NULL)
{
MessageBox(NULL, (LPCWSTR)LocalLock(hlocal), (LPCWSTR)"CLIENT ERROR", MB_OK);
LocalFree(hlocal);
}
} /*
* 初始化成员变量
*/
void InitMember(void)
{
//初始化读和写缓冲区
memset(bufRecv, , MAX_NUM_BUF);
memset(bufSend, , MAX_NUM_BUF);
//初始化
sHost = INVALID_SOCKET;
//没有连接状态
bConning = FALSE;
} /*
* 退出
*/
int ExitClient(int nExit)
{
closesocket(sHost); //关闭套接字
WSACleanup(); //卸载Windows sockets DLL 清理内存 //显示退出信息
cout << "客户端正在退出..." << endl;
Sleep();
return nExit; //退出
} /*
* 读取一行数据
*/
BOOL RecvLine(SOCKET s, char* buf)
{
BOOL retVal = TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = ; //读入字节数
int nDataLen = ; //数据长度
while (!bLineEnd && bConning) //与客户端连接 没有换行
{
nReadLen = recv(s, buf + nDataLen, , );//每次接收一个字节
//错误处理
if (SOCKET_ERROR == nReadLen)
{
retVal = FALSE; //读数据失败
break; //跳出循环
} if ( == nReadLen)//客户端关闭
{
retVal = FALSE; //读数据失败
break; //跳出循环
} //读入数据
if ('\n' == *(buf + nDataLen)) //换行符
{
bLineEnd = TRUE; //接收数据结束
}
else {
nDataLen += nReadLen; //增加数据长度
}
} return retVal;
}

windows套接字阻塞模式编程实例的更多相关文章

  1. TCP/UDP套接字 java socket编程实例

    网络协议七层结构: 什么是Socket? socket(套接字)是两个程序之间通过双向信道进行数据交换的端,可以理解为接口.使用socket编程也称为网络编程,socket只是接口并不是网络通信协议. ...

  2. windows套接字相关函数

    windows套接字相关函数 作者:vpoet mail:vpoet_sir@163.com 我们学习TCP/IP协议无非是利用这些协议进行通信开发,然而如果让我们自己来直接根据协议规则和协议格式来进 ...

  3. 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .

    命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...

  4. 缺少网络连接需要的Windows套接字注册表项(浏览器无法连网)

      缺少网络连接需要的Windows套接字注册表项(浏览器无法连网) CreateTime--2018年4月25日14:17:42 Author:Marydon 1.异常信息 此计算机上缺少一个或多个 ...

  5. Python中利用原始套接字进行网络编程的示例

    Python中利用原始套接字进行网络编程的示例 在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构 ...

  6. 基于TCP的socket套接字的网络编程(客户端/服务端模式)

    于数据完整性要求较高的场合,就应采用TCP协议. IP网络层提供IP寻址和路由.因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路. IP地址与数据包: IP层就是把数据分组从一 ...

  7. java套接字(socket)实例

    客户端socket 流程: 1.连接远程主机 2.发送数据 3.接收数据 4.关闭流与socket连接 实例: import java.io.*; import java.net.Socket; im ...

  8. 5-tcp套接字服务端编程

    import socket 1.创建套接字 sockfd= socket.socket(socket_family = AF_INIT,socket_type=SOCK_STREAM,proto) 功 ...

  9. iptables开启后造成本地套接字阻塞的问题

    前段时间,我使用iptables实现了针对IP地址与MAC地址的白名单功能,即将INPUT链的默认规则设为DROP: iptables -P INPUT DROP 这样就能拒绝一切外来报文.随后只需要 ...

随机推荐

  1. 湖南省第十二届省赛:Parenthesis

    Description Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions. The i-t ...

  2. Spring Boot教程(四)接收上传的multi-file的文件

    构建工程 为例创建一个springmvc工程你需要spring-boot-starter-thymeleaf和 spring-boot-starter-web的起步依赖.为例能够上传文件在服务器,你需 ...

  3. Hive数据导入Elasticsearch

    Elasticsearch Jar包准备 所有节点导入elasticsearch-hadoop-5.5.1.jar /opt/cloudera/parcels/CDH-5.12.0-1.cdh5.12 ...

  4. 关于R语言中set.seed()

    在r中取sample时候,经常会有set.seed(某数),经常看见取值很大,其实这里无论括号里取值是多少,想要上下两次取值一样,都需要在每次取值前输入同样的set.seed(某数),才能保证两次取值 ...

  5. Ansible安装及常用模块

    配置文件:/etc/ansible/ansible.cfg 主机列表:/etc/ansible/hosts  安装anslibe  wget -O /etc/yum.repos.d/epel.repo ...

  6. React Native商城项目实战02 - 主要框架部分(tabBar)

    1.安装插件,cd到项目根目录下执行: $ npm i react-native-tab-navigator --save 2.主框架文件Main.js /** * 主页面 */ import Rea ...

  7. leetcode-easy-array-1 two sum

    mycode  33.91% class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: for i ...

  8. VS调试异常代码 HRESULT:0x80070057 (E_INVALIDARG)解决方法

    我目前在做的一个系统是VS2010写的的B/S架构程序, 主要技术是:C#.SQLSERVER2008.NHibernate,Python,Nhibernate 的*.hbn.xml是映射数据库的表结 ...

  9. Service层获取HttpServletRequest request

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/liuyunshengsir/article/details/78183058HttpServletR ...

  10. jenkins中通过Publish Over SSH将项目部署到远程机器上

    Publish Over SSH插件使用在使用Publish Over SSH之前,需要制作SSH私钥.机器间做免密登录配置.假设机器A,ip为192.168.AA.AAA,机器B: 192.168. ...