linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解
最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展,2.0之后更是如此)。从实现的角度来说,跟c/c++开发一样,windows和Linux就是两大阵营,除了标准c/c++部分外,有着各自大量的扩展特性。这个例子比较有点像是关系型数据库,标准都是ISO SQL,但是实现机制、性能、API等,每个数据库厂家都不同,比如oracle/mysql/postgresql都是各有所长。
windows下是:
#include<winsock.h>
#include<winsock2.h>
说白了winsock2.h是winsock.h的升级版,一般而言没有必要使用winsock(其实winsock2是98年公布的,winsock(winsock借鉴了berkeley socket api的思想)则是93年,完全算不上新,98之后的系统已经完全支持了并且是现在的标准,微软于2015年7月终止了对windows 2003的支持),具体差别baidu也可以看到,或者参考《windows sockets网络编程》,windows网络编程不可多得的参考书之一。
linux下是:
#include <netinet/in.h> //大部分都在这儿
#include <unistd.h> // close函数在这儿
#include <sys/socket.h> // 在in.h里已经包含了,可以省了
#include <errno.h> // 错误处理
#include <sys/types.h> // 系统类型定义
因为我们的客户端应用跑在windows下,所以下面重点讲讲windows socket编程,入门官方资料可参考 Getting Started With Winsock https://msdn.microsoft.com/en-us/library/windows/desktop/ms738545(v=vs.85).aspx。
在winsock中,提供了两套用于网络编程的接口,一套是很接近标准berkeley也就是Linux下的socket api,几乎现行大部分的网络编程书籍都是基于linux的(一般在实际的编程中,考虑到尽可能减少平台差异问题,会采用尽可能接近标准 socket api的接口)。另外一套则是微软专用的以WSA开头的接口,前者通常接口名都是关键字,后者则基本上都是WSA开头+驼峰式的标准socket api名称。如下:


标准socket接口仅支持同步,专用socket接口支持异步、线程安全等特性。
关于c/c++和java编程的区别可参考博文。http://www.cnblogs.com/zhjh256/p/6007365.html。
winsock在ISO中的角色如下:


winsock2的库文件是Ws2_32.lib。对于tcp/ip编程而言,主要是有两个头文件:
Winsock2.h
Ws2tcpip.h
还有一个可选的iphlpapi.h,这个一个IP帮助器API。
首先建立一个空的visual c++工程,创建一个空的c++文件。
然后包含相关的头文件:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif #include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h> #pragma comment(lib, "Ws2_32.lib") int main() {
return ;
}
然后初始化winsock,如下所示:
int main() {
WSADATA wsaData; //其中包含关于Windows Sockets的详细实现
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(,), &wsaData); //用于初始化WS2_32.dll的使用,MAKEWORD(2,2)设置供后续socket调用者使用的最高winsock版本
if (iResult != ) {
printf("WSAStartup failed: %d\n", iResult);
return ;
}
}
struct addrinfo *result = NULL,
*ptr = NULL,
hints; ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET; //关于IP地址族有三个取值,AF_INET:ipv4 AF_INET6:ipv6 AF_UNSPEC:任意,所以一般现在使用ipv4
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; //表示协议类型,一般应该显示指定,否则默认有可能实现会去获取ipv4,这取决于运行的OS类型,因为每个版本的winsock都在更新,具体变更可参考https://msdn.microsoft.com/en-us/library/windows/desktop/ms740642(v=vs.85).aspx // Resolve the server address and port
iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
if (iResult != ) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return ;
} SOCKET ConnectSocket = INVALID_SOCKET; // Attempt to connect to the first address returned by
// the call to getaddrinfo
ptr=result; // Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return ;
} // Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
} // Should really try the next address returned by getaddrinfo
// if the connect call failed
// But for this simple example we just free the resources
// returned by getaddrinfo and print an error message freeaddrinfo(result); if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return ;
}
struct test {
unsigned int len;
char name[];
}; int recvbuflen = DEFAULT_BUFLEN; char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN]; unsigned int len = htonl(strlen(sendbuf)); //得到报文长度且必须从主机字节顺序转换为网络字节顺序,收包时使用ntohl, 这里假设报文长度用32位整形 iResult; // Send an initial buffer
iResult = send(ConnectSocket, (char*)&len, sizeof(unsigned int), ); //先发送报文长度,这在实际网络编程下是惯例,可以说没有一个系统是采用固定长度报文的
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), ); //发送报文数据本身
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return ;
} printf("Bytes Sent: %ld\n", iResult); // shutdown the connection for sending since no more data will be sent
// the client can still use the ConnectSocket for receiving data
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return ;
} // Receive data until the server closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, );
if (iResult > )
printf("Bytes received: %d\n", iResult);
else if (iResult == )
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (iResult > );
跟java socket一样,winsock2,也都提供下列特性:
1、支持异步IO和事件;
2、支持设置socket参数;
3、socket线程安全,多任务可以同时操作。
linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解的更多相关文章
- windows socket函数详解
windows socket函数详解 近期一直用第三方库写网络编程,反倒是遗忘了网络编程最底层的知识.因而产生了整理Winsock函数库的想法.以下知识点均来源于MSDN,本人只做翻译工作.虽然很多前 ...
- socket编程的同步、异步与阻塞、非阻塞示例详解
socket编程的同步.异步与阻塞.非阻塞示例详解之一 分类: 架构设计与优化 简介图 1. 基本 Linux I/O 模型的简单矩阵 每个 I/O 模型都有自己的使用模式,它们对于特定的应用程序 ...
- java网络编程Socket通信详解
Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术. ...
- 【转载】Linux字符集和系统语言设置-LANG,locale,LC_ALL,POSIX等命令及参数详解
Linux字符集和系统语言设置-LANG,locale,LC_ALL,POSIX等命令及参数详解 1清风揽月10人评论5006人阅读2017-06-21 15:48:43 博文说明[前言]: 本文 ...
- 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解
Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解 多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...
- TCP/IP协议、HTTP协议、SOCKET通讯详解
1.TCP连接TCP(Transmission Control Protocol) 传输控制协议.TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握确认建立一个连接.位码即tcp标志位 ...
- Linux 网络编程三(socket代码详解)
//网络编程客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include < ...
- TCP协议的3次握手与4次挥手过程【深度详解】
一.前沿 尽管TCP和UDP都使用相同的网络层(IP),TCP却向应用层提供与UDP完全不同的服务.TCP提供一种面向连接的.可靠的字节流服务.面向连接意味着两个使用TCP的应用(通常是一个客户和一个 ...
- 记Windows下初次使用dev C++进行socket编程过程
记初次接触socket编程,在devC++使用Winsock进行socket编程的一个过程,通过在devC++创建2个项目分别是server.client程序项目,感受通过socket使client与 ...
- HTTP、TCP、UDP、Socket关系详解
TCP.UDP和HTTP关系是什么? 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层.在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议.在传输层中有TCP ...
随机推荐
- SQL SERVER 2008 如何查询含有某关键词的表
最新文章:Virson's Blog 文章来自:百度知道 /** 查询一个数据库中所有的数据中是否包含指定字符串 */ ) set @str='字符串' --要搜索的字符串 ) declare tb ...
- dialog横竖屏切换时消失的解决方法
声明 本文原创,转载请注明来自xiaoQLu http://www.cnblogs.com/xiaoQLu/p/3324764.html dialog的生命周期依赖创建他的activity,怎么设置横 ...
- Android Studio开发第四篇版本管理Git(下)
前面一片介绍了在as下如何关联远程仓库,这篇就介绍在开发过程中怎么应用. 提交+Push 如果本地开发代码有改动了或者你觉得某功能做完了,你打算把改动代码提交到远程仓库,这个时候很简单, 还是在工具栏 ...
- php 基础知识
一.判断代码输出 $str1 = null; $str2 = false; echo $str1==$str2 ? '相等' : '不相等'; $str3 = ''; $str4 = 0; echo ...
- npm命令总结
统一切换到项目目录 安装redux :npm install -save redux 安装react-redux : npm install -save react-redux
- 拼音 名字 排序 a-z的比较 ( sortUsingComparator )
NSMutableArray * array = [NSMutableArrayarrayWithObjects:@"ad",@"az",@"ac&q ...
- SVN分支与合并
分支的基本概念就正如它的名字,开发的一条线独立于另一条线,如果回顾历史,可以发现两条线分享共同的历史,一个分支总是从一个备份开始的,从那里开始,发展自己独有的历史(如下图所示) ⑴创建分支 假设目前我 ...
- Logstash日志搜集
软件准备: logstash-2.1.0.zip elasticsearch-2.1.0.zip kibana-4.3.0-windows.zip Redis-x64-2.8.2104.msi 下载地 ...
- linux2.6.24内核源代码分析(2)——扒一扒网络数据包在链路层的流向路径之一
在2.6.24内核中链路层接收网络数据包出现了两种方法,第一种是传统方法,利用中断来接收网络数据包,适用于低速设备:第二种是New Api(简称NAPI)方法,利用了中断+轮询的方法来接收网络数据包, ...
- Hadoop第5周练习—MapReduce计算气象温度等例子
:对云计算的看法 内容 :使用MapReduce求每年最低温度 内容 :求温度平均值能使用combiner吗? 内容 :使用Hadoop流求最高温度(awk脚本) 内容 :使用Hadoop流求最高温度 ...