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

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. Codeforces 1203F1 Complete the Projects (easy version)

    cf题面 Time limit 2000 ms Memory limit 262144 kB 解题思路 看见这题觉得贪心可做,那就贪吧.(昨天真是贪心的一天,凌晨才被这两道贪心题虐,下午多校又来,感觉 ...

  2. FJWC2017&FJOI2017一试 游记

    day1 ​ 早上是以前泉州七中的杨国烨讲课.(据说当时看新闻说是一对双胞胎一起上thu的其中一个)课题是图论/网络流. ​ 下午第一道一开始推出来了一个之和面积有关的式子,然后觉得可以容斥一发,觉得 ...

  3. (59)Linux操作系统深入应用

    目录: 第一部分:嵌入式的含义 第二部分:DOS命令 第三部分:linux的发展历史(与unix的关系) 第四部分: 基于ubuntu下的linux命令详解大全         第一部分:嵌入式的含义 ...

  4. android实现异步加载图片类

    其中牵涉到的关键知识点 1,回调机制,不过回调接口的实现方式有多种多样,可以是一个类继承该接口,也可以是作为一个方法参数: 可以参照自己的这篇博客: http://www.cnblogs.com/bo ...

  5. vsCode格式化插件

    ESlint:是用来统一JavaScript代码风格的工具,不包含css.html等. 背景 近来研究前端,然后一直在百度上找VScode格式化(ESlint)的插件,结果找了半天都不靠谱.目前没有一 ...

  6. pymysql(一)检索、增加、更新、删除数据

    (一)  SELECT 检索数据 代码如下: import pymysql '''pymysql使用指南host = '127.0.0.1'回送地址,指本地机port = 3306MySQL的默认端口 ...

  7. centos7 开机启动运行脚本

    /etc/profile.d 下建立一个xxxname.sh

  8. 彩色点云生成mesh的纹理

    上一篇文章 https://www.cnblogs.com/lovebay/p/11423576.html ,我们使用MPA算法实现了 点云生成mesh,但仅仅实现mesh的顶点着色,为了让mesh有 ...

  9. zay大爷的神仙题目 D1T1-大美江湖

    在前几天的时候,千古神犇zay(吊打zhx那个)出了一套神仙题目,所以我得来分析分析QWQ 先补个网易云链接QWQ 毕竟是T1嘛,还算是比较简单的,那道题,读完题目就发现是个中等模拟(猪国杀算大模拟的 ...

  10. MySql 使用递归函数时遇到的级联删除问题

    以下两段SQL的写法看似相同,结果效果却是不同的 写法A: DELETE OM_ORGANIZATION, OM_POSITION FROM OM_ORGANIZATION LEFT JOIN OM_ ...