windows套接字阻塞模式编程实例
一、阻塞模式套接字服务端和客户端的运行流程如下:
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套接字阻塞模式编程实例的更多相关文章
- TCP/UDP套接字 java socket编程实例
网络协议七层结构: 什么是Socket? socket(套接字)是两个程序之间通过双向信道进行数据交换的端,可以理解为接口.使用socket编程也称为网络编程,socket只是接口并不是网络通信协议. ...
- windows套接字相关函数
windows套接字相关函数 作者:vpoet mail:vpoet_sir@163.com 我们学习TCP/IP协议无非是利用这些协议进行通信开发,然而如果让我们自己来直接根据协议规则和协议格式来进 ...
- 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .
命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...
- 缺少网络连接需要的Windows套接字注册表项(浏览器无法连网)
缺少网络连接需要的Windows套接字注册表项(浏览器无法连网) CreateTime--2018年4月25日14:17:42 Author:Marydon 1.异常信息 此计算机上缺少一个或多个 ...
- Python中利用原始套接字进行网络编程的示例
Python中利用原始套接字进行网络编程的示例 在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构 ...
- 基于TCP的socket套接字的网络编程(客户端/服务端模式)
于数据完整性要求较高的场合,就应采用TCP协议. IP网络层提供IP寻址和路由.因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路. IP地址与数据包: IP层就是把数据分组从一 ...
- java套接字(socket)实例
客户端socket 流程: 1.连接远程主机 2.发送数据 3.接收数据 4.关闭流与socket连接 实例: import java.io.*; import java.net.Socket; im ...
- 5-tcp套接字服务端编程
import socket 1.创建套接字 sockfd= socket.socket(socket_family = AF_INIT,socket_type=SOCK_STREAM,proto) 功 ...
- iptables开启后造成本地套接字阻塞的问题
前段时间,我使用iptables实现了针对IP地址与MAC地址的白名单功能,即将INPUT链的默认规则设为DROP: iptables -P INPUT DROP 这样就能拒绝一切外来报文.随后只需要 ...
随机推荐
- 【canvas学习笔记六】状态保存和变换
save()和restore() save() 保存当前状态,将当前canvas的状态存入栈中. restore() 恢复之前save的一个状态,将之前的状态从栈中弹出. 保存的当前状态包含以下信息: ...
- Oracle-分配用户只读存储过程权限
系统新来了系统运维人员,要求创建数据库账号,只分配对表,视图,存储程序有只读权限 因为表和视图权限接触比较频繁,所以今天花点时间整理下关于存储过程的权限 关于ORACLE账号的权限问题,一般分为两种权 ...
- sqli-labs(19)
百度了一下 基于错误的referer头的注入 0X01爱之初体验 猜测是基于referer头的注入 我们在referer后面加入单引号测试一下 真的报错了诶 那我们猜测一下 他应该是把 referer ...
- 测试相关shell命令总结2——结构控制语句,命令行参数
1,shell 中单引号和双引号的区别,单引号不进行解释.双引号进行解释 1,在shell中进行数学运算,放在$和[]中 $[1+2] 有些很奇怪,在.sh文件中放在(())中貌似也能够进行数学运算. ...
- C++学习一二
为了更深入的学习程序编写,以及进行相关算法的编写.决定每天花点时间学习C++:以下是每天的学习笔记. 一.std代表命名空间,可以用using来省略. 二.std:endl.输出一个换行符,并且“刷新 ...
- Comparable接口与Comparator接口的比较————总结
之前的两篇文章主要学习了Comparable接口和Comparator接口的学习.既然已经学习完了,现在就趁热打铁,进行总结吧! Comparable接口和Comparator接口的共同点: 1. 都 ...
- leetcode-easy-array-50. Intersection of Two Arrays II
mycode 77.78% class Solution(object): def intersect(self, nums1, nums2): """ :type n ...
- 阶段2 JavaWeb+黑马旅游网_15-Maven基础_第1节 基本概念_03maven一键构建概念
资料里面写好的Helloworld项目 pom.xml存放jar包的坐标 首先复制项目所在的目录的路径: 先进去复制的这个路径,然后又输入了d盘.这时候就进去到这个项目目录了. 这个项目就运行起来了. ...
- ubuntu16.04 卸载及安装MySQL
以MySQL- 5.7.18为例: sudo apt-get autoremove --purge mysql-server-5.7 #sudo apt-get remove mysql-server ...
- 编写Python脚本把sqlAlchemy对象转换成dict的教程
编写Python脚本把sqlAlchemy对象转换成dict的教程 在用sqlAlchemy写web应用的时候,经常会用json进行通信,跟json最接近的对象就是dict,有时候操作dict也会比操 ...