Windows网络通信(一):socket同步编程
网络通信常用API
1. WSAStartup用于初始化WinSock环境
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);wVersionRequested:当前进程能够使用Windows Socket的最高版本,目前指定2.2即可。
lpWSAData:指向一个WSAData结构体,接受Socket详细信息。
成功返回0
2. socket建立一个指定类型的SOCKET用于通信
SOCKET WSAAPI socket(
int af,
int type,
int protocol
);af:address family,指定用于通信的网络地址类型,可以取值AF_INET(IPv4),AF_INET6(IPv6),AF_BTH(蓝牙)等。
type:指定传输类型,可以取值SOCK_STREAM(用于TCP),SOCK_DGRAM(用于UDP)等。
protocol:通信协议,可以取值IPPROTO_TCP,IPPROTO_UDP等。
成功返回一个可以用于通信的SOCKET,否则返回INVALID_SOCKET。
3. bind将socket和网络地址和端口绑定起来
int bind(
SOCKET s,
const struct sockaddr *name,
int namelen
);s:一个未绑定的socket。
name:指向一个sockaddr对象,用于指定绑定的ip和端口信息。
namelen:sockaddr的长度,为什么这里还需要指定长度呢,因为name是根据socket的类型来指定不同的结构体的,可能是sockaddr_in(IPv4)或者sockaddr_in6(IPv6)。
成功返回0
4. listen将SOCKET设为监听状态,可以被客户端连接
int listen(
SOCKET s,
int backlog
);s:一个未被连接的socket
backlog:可以连接的客户端的最大数目,如果指定为SOMAXCONN,则设置为最大的连接数量。
成功返回0
5. send通过指定socket发送数据
int send(
SOCKET s,
const char *buf,
int len,
int flags
);s:一个已经连接的socket。
buf:待发送数据
len:待发送数据的长度
flags:发送的一个标志设定,一般设为0
成功返回已发送的字节数目。这个数目可能小于len的。失败返回SOCKET_ERROR。
6. recv通过指定的socket接受数据
int recv(
SOCKET s,
char *buf,
int len,
int flags
);s:一个已经连接的socket
buf:接收数据的缓存区
len:缓存区长度
flags:接受数据的一个标志,一般设为0。
成功返回已接受数据的长度,失败返回SOCKET_ERROR,如果已经断开连接,返回0
7. shutdown关闭一个SOCKET的send或者recv功能
int shutdown(
SOCKET s,
int how
);s:socket
how:指定该socket的某个功能不需要再使用,可以取值SD_RECEIVE(接收功能),SD_SEND(发送功能),SD_BOTH(发送和接收功能)。
成功返回0,失败返回SOCKET_ERROR
8. connect连接到服务端,服务端开启listen后,客户端就可以使用connect进行连接
int connect(
SOCKET s,
const struct sockaddr *name,
int namelen
);s:一个未连接的socket
name,namelen:和bind中name,namelen参数一样
成功返回0,失败返回SOCKET_ERROR
9. closesocket关闭一个已经存在的socket
int closesocket(
SOCKET s
);s:一个待关闭的socket。
成功返回0,失败返回SOCKET_ERROR
10. accept接收一个来自客户端的连接
SOCKET accept(
SOCKET s,
struct sockaddr *addr,
int *addrlen
);s:一个已经listen的socket
addr:用于储存接收到的客户端的sockaddr信息
addrlen:连接的客户端的sockaddr长度。
socket通信示例
服务端和客户端测试代码
// NetWork1.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 12345 //启动客户端
int startClient()
{
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char *sendbuf = "[Client]:客户端测试文本";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN; // 创建一个TCP套接字
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket创建失败: %ld\n", WSAGetLastError());
WSACleanup();
return ;
} // 指定连接端口和ip信息
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
clientService.sin_port = htons(DEFAULT_PORT); // 连接服务端
iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR) {
printf("连接失败: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return ;
} if (ConnectSocket == INVALID_SOCKET) {
printf("无法连接到指定服务端!\n");
WSACleanup();
return ;
} // 发送一段数据
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), );
if (iResult == SOCKET_ERROR) {
printf("发送数据失败: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return ;
} printf("已发送数据大小: %ld\n", iResult); // 关闭发送功能,但是仍然可以接收
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("关闭发送功能失败: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return ;
} // 接收数据
do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, );
if (iResult > )
printf("已接收: %d\n", iResult);
else if (iResult == )
printf("连接关闭\n");
else
printf("接收数据失败: %d\n", WSAGetLastError()); } while (iResult > ); //关闭套接字
closesocket(ConnectSocket);
WSACleanup();
return ;
} int startServer()
{
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
sockaddr_in service;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
char *sendbuf = "[Server]:服务端测试文本"; // 创建TCP套接字
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("socket创建失败: %ld\n", WSAGetLastError());
WSACleanup();
return ;
}
// 设定绑定的ip和端口信息
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(DEFAULT_PORT); // 绑定套接字
iResult = bind(ListenSocket, (SOCKADDR *)&service, sizeof(service));
if (iResult == SOCKET_ERROR) {
printf("套接字绑定失败:%d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return ;
} iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("套接字监听失败: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return ;
} // 接受来自客户端的连接
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return ;
} // 关闭服务端套接字,表示不需要再接收新的客户端连接了,但是已经连接的套接字还是能通信
closesocket(ListenSocket); do {
//接收来自客户端的消息
iResult = recv(ClientSocket, recvbuf, recvbuflen, );
if (iResult > ) {
printf("已接收数据大小: %d\n", iResult); // 发送数据到客户端,这里就是将数据
iSendResult = send(ClientSocket, sendbuf, (int)strlen(sendbuf), );
if (iSendResult == SOCKET_ERROR) {
printf("发送失败: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return ;
}
printf("发送字节大小: %d\n", iSendResult);
}
else if (iResult == )
printf("连接已关闭\n");
else {
printf("接收数据失败: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return ;
}
} while (iResult > ); //关闭套接字以及清理套接字环境
closesocket(ClientSocket);
WSACleanup(); return ;
}
int main(int argc, char *argv[])
{
int iResult;
WSADATA wsaData;
//初始化套接字环境
iResult = WSAStartup(MAKEWORD(, ), &wsaData);
if (iResult != ) {
printf("初始化socket环境失败: %d\n", iResult);
return ;
}
if (argc == && strcmp(argv[], "c") == )
{
//客户端
return startClient();
}
else if (argc == && strcmp(argv[], "s") == )
{
//服务端
return startServer();
}
return ;
}
运行结果
后记
以上只是一个简单的socket通信示例,所有api调用都是阻塞的,非阻塞调用将在下文写出。
Windows网络通信(一):socket同步编程的更多相关文章
- windows下的socket网络编程
windows下的socket网络编程 windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了, ...
- windows下的socket网络编程(入门级)
windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先 ...
- Cfree clion windows c语言 socket 网络编程
server.c #include <stdio.h> #include <winsock2.h> #define SERVER_PORT 5208 //侦听端口 int ma ...
- Windows网络通信(二):socket异步编程
简述 这里使用的API和同步编程的API是差不多的,只多了一个ioctlsocket和select函数.这里面涉及一个很重要的结构体fd_set.这里用到的API大部分都是windows和linux通 ...
- winsock教程- windows下的socket编程(c语言实现)
winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程 这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下 ...
- windows socket网络编程基础知识
下面介绍网络7层协议在WINDOWS的实现: 7层协议 WIN系统 ________________________________________ 7 应用层 7 应用程序 ____________ ...
- windows socket 网络编程
样例代码就在我的博客中,包含六个UDP和TCP发送接受的cpp文件,一个基于MFC的局域网聊天小工具project,和此小工具的全部执行时库.资源和执行程序.代码的压缩包位置是http://www.b ...
- C#网络编程系列(两)它Socket同步TCPserver
声明原文 笔者:竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程系列文 ...
- 基于C++简单Windows API的socket编程(阻塞模式)
1. 概述:简单的基于Windows API的socket点对点聊天程序,为了方便初学者,本文代码均采用阻塞原理编写. 2. 代码样例 Server.cpp(服务端) #include <cst ...
随机推荐
- RedHat(小红帽)下 yum用不了的解决办法
由于RedHat是商业版的,通常由于没有注册,导致yum程序无法使用(linux下面,yum是个安装软件的“神器”).此时可用CentOS的地址进行替换.下面将一步步说明如何处理: 一.删除RedHa ...
- HTML小记
1.页面内跳转 当<a>元素用于页面内的锚点跳转时,应该先为该页面设置一些锚点,而定义锚点有两种办法: 通过<a>元素的name属性来定义,如:<a name=" ...
- java工作流引擎 Activiti6.0 websocket 即时聊天发图片文字 好友群组 SSM源码
时通讯:支持好友,群组,发图片.文件,消息声音提醒,离线消息,保留聊天记录 工作流模块--------------------------------------------------------- ...
- oracle的建表语句
oracle数据库的建表语句,具体语法如下: CREATE TABLE tablename (column_name datatype [null,not null], column_name dat ...
- oracle安装程序异常终止解决办法
安装Oracle时总是会报程序异常终止,摸不着头脑,作为初学者一下就乱了分寸 工具/原料 Oracle软件包 win764位 方法/步骤 右击Oracle安装图标setup.exe,选 ...
- android学习1:清晰详细android环境搭建,超简单
废话少说,今天是Android学习的开篇的博客,接下来将把自己学习android的各种问题和经历总结一下,其实之前已经自己学过半年了,但是因为开始时刚学的移动端开发还没有概念,当时总结工作又做的不好, ...
- crashes
iOS 僵尸对象调试 - 简书 iOS APP审核被拒的解决之道(2.1) - - ITeye博客 iOS应用崩溃日志分析 - CocoaChina 苹果开发中文站 - 最热的iPhone开发社区 最 ...
- #leetcode刷题之路31-下一个排列
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列.如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列).必须原地修改,只允许使用额外常数空间. 以下 ...
- Android Studio 2.3.3 出现Error:(26.13) Fail to resole: com.android.support.appcompat永久解决方法
Android Studio 出现Error(26.13):Fail to resole:com.android.support.appcompat-v7.28_ Install Repository ...
- lrzsz Linux服务器Windows互传文件工具
lrzsz是一款在linux里可代替ftp上传和下载的程序,但只限于较小的文件,如果是目录需要打包成单个文件在实现下载. 条件:需要使用SecureCRT或者Xshell等客户端工具连接Linux 下 ...