Windows 网络编程基于TCP协议的Socket通信
来源:互联网 发布:数学算法 编辑:程序博客网 时间:2024/05/19 12:38
Socket套接字,是TCP/IP网络环境下应用程序与底层通信驱动程序之间运行开发接口,可以将应用程序与具体的TCP/IP隔离开来,使得应用程序不需要了解TCP/IP的具体细节,就能够实现数据传输。
在Socket通信中,套接字分为3中类型:
1. 流式套接字
提供面向连接的、可靠地数据传输服务,可以无差错地发送数据。传输数据可以是双向的字节流,即应用程序采用全双工方式,通过套接字同时传输和接收数据。应用程序可以通过流传递有序的、不重复的数据,即数据包按发送顺序送达目的地址,且一个特定的数据包只能获取一次。适用于可靠且数据量大的传输。
2.数据报式套接字
提供面向无连接的数据传输服务。数据包被独立发送,数据可能丢失或重复。
3.原始套接字
公开的Socket编程接口,可以在IP层上对Socket进行编程,发送和接收IP层上的原始数据包。
根据底层协议不同,Socket开发接口可以提供面向连接和无连接两种服务方式。
在面向连接的服务方式中,每次完整的数据传输都要经过建立连接、使用连接和关闭连接的过程。连接相当于一个传输管道,因此在数据传输过程中,分组数据包中不需要指定目的地址。TCP提供面向连接的虚电路。
在Socket通信中,套接字分为3中类型:
1. 流式套接字
提供面向连接的、可靠地数据传输服务,可以无差错地发送数据。传输数据可以是双向的字节流,即应用程序采用全双工方式,通过套接字同时传输和接收数据。应用程序可以通过流传递有序的、不重复的数据,即数据包按发送顺序送达目的地址,且一个特定的数据包只能获取一次。适用于可靠且数据量大的传输。
2.数据报式套接字
提供面向无连接的数据传输服务。数据包被独立发送,数据可能丢失或重复。
3.原始套接字
公开的Socket编程接口,可以在IP层上对Socket进行编程,发送和接收IP层上的原始数据包。
服务端的示例代码:
// TCP Socket.cpp : 定义控制台应用程序的入口点。// TCPServer服务器程序#include "stdafx.h" //默认包含的头文件,用于实现头文件的预编译#include<WINSOCK2.H> //用于管理WIndows Sockets版本2函数的头文件#include<iostream> //用于管理输入输出流的头文件#pragma comment(lib,"WS2_32.lib")#define BUF_SIZE 128 //缓冲区大小#define PORT 9990int _tmain(int argc, _TCHAR* argv[]){ //声明变量 WSADATA wsd; //wsadata变量,初始化Windows socket SOCKET sServer; //服务器Socket,用于监听客户端的请求 SOCKET sClient; //客户端Socket,用于实现与客户端的通信 int retVal; //调用各种Socket函数的返回值 int on; //设置setsocket参数时使用 char buf[BUF_SIZE]; //初始化Socket动态库 if (WSAStartup(MAKEWORD(2,2),&wsd)!=0) { printf("WSAStartup failed !\n"); return -1; } //创建用于监听的Socket sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (INVALID_SOCKET == sServer) { printf("Socket failed!\n"); WSACleanup(); return -1; } else printf("Create Socket OK\n"); on = 1; setsockopt(sServer, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); //允许地址重用 //设置服务器Socket地址 SOCKADDR_IN addrServ; addrServ.sin_family = AF_INET; //地址家族 addrServ.sin_port = htons(9990); //端口 addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //地址,host_id转为net_id,类型u_long //绑定Socket Server到本地地址 retVal = bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN)); if (SOCKET_ERROR == retVal) { printf("bind failed ! \n"); closesocket(sServer); WSACleanup(); return -1; } printf("socket bind OK!\n"); //在Socket Server上进行监听 retVal = listen(sServer, 1); if (SOCKET_ERROR == retVal) { printf("listen failed!/n"); closesocket(sServer); WSACleanup(); return -1; } printf("socket listen OK!\n"); //接收来自客户端的请求 printf("TCP Server start....\n"); sockaddr_in addrClient; int addrClientlen = sizeof(addrClient); sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen); if (INVALID_SOCKET == sServer) { printf("accept failed! \n"); closesocket(sServer); WSACleanup(); return -1; } printf("accept a connect request !\n"); //在服务器与客户端之间收发数据 while (true) { //循环接收数据,直到客户端发送“quit”后退出 ZeroMemory(buf, BUF_SIZE); retVal = recv(sClient, buf, BUFSIZ, 0); if (SOCKET_ERROR == retVal) { printf("recv failed! \n"); closesocket(sClient); WSACleanup(); return -1; } if (retVal == 0) //0代表客户端断开连接 { printf("socket close connection.\n"); closesocket(sClient); return -1; } //获取系统当前时间 SYSTEMTIME st; GetLocalTime(&st); char sDataTime[30]; sprintf_s(sDataTime,"%4d-%2d-%2d %2d-%2d-%2d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond); printf("\nTime[%s]\n Recv from Client[%s:%d]:%s\n",sDataTime,inet_ntoa(addrClient.sin_addr),addrClient.sin_port,buf); char msg[BUF_SIZE]; sprintf_s(msg, "%s", buf); //输出到字符串msg中 for (int i = 0; i < sizeof(msg); i++) //将接收到的数据转为大写 msg[i] = toupper(msg[i]); retVal = send(sClient, msg, strlen(msg), 0); if (SOCKET_ERROR == retVal) { printf("send failed !\n"); closesocket(sServer); closesocket(sClient); WSACleanup(); return -1; } } //释放资源 closesocket(sServer); closesocket(sClient); WSACleanup(); //暂停,按任意键退出 system("pause"); return 0;}
客户端的示例代码:
// TcpSocketClient.cpp : 定义控制台应用程序的入口点。// TCP Client 客户端程序#include "stdafx.h"#include<WINSOCK2.H>#include<string>#include<iostream>#pragma comment(lib,"WS2_32.lib")#define BUF_SIZE 128#define PORT 9990int _tmain(int argc, _TCHAR* argv[]){ //声明变量 WSADATA wsd; //用于初始化windows socket SOCKET sHost; //与服务器进行通信的socket SOCKADDR_IN servAddr; //服务器地址 char buf[BUF_SIZE]; //接收数据缓冲区 int retVal; //调用各种socket函数的返回值 //初始化Socket环境 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup failed !\n"); return 1; } //创建用于通信的Socket sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == sHost) { printf("socket faild !\n"); WSACleanup(); return -1; } //设置服务器的Socket地址 servAddr.sin_family = AF_INET; servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //servAddr.sin_addr.S_un.S_addr = inet_addr("172.18.147.35"); servAddr.sin_port = htons(PORT); int sServerAddlen = sizeof(servAddr); //连接到服务器 retVal = connect(sHost, (SOCKADDR*)&servAddr, sizeof(servAddr)); if (SOCKET_ERROR == retVal) { printf("connect failed!\n"); closesocket(sHost); WSACleanup(); return -1; } printf("socket connect OK!\n"); //服务器和客户端收发数据 while (true) { printf("Please input a string to send: "); std::string str; std::getline(std::cin, str); ZeroMemory(buf, BUF_SIZE); strcpy_s(buf, str.c_str()); //注意recv和send是阻塞的,不能同时收发 retVal = send(sHost, buf, strlen(buf), 0); if (SOCKET_ERROR == retVal) { printf("send failed!\n"); closesocket(sHost); return -1; } //服务器接收回传的数据 retVal = recv(sHost, buf, sizeof(buf), 0); if (SOCKET_ERROR == retVal) { printf("receive failed!\n"); closesocket(sHost); return -1; } printf("Recv From Server: %s\n", buf); //释放资源 closesocket(sHost); WSACleanup(); system("pause"); return 0; }}
代码说明:
示例代码实现了服务端接收客户端发来的字符串,然后将所有字符串转为大写字母,再重新发回到客户端。
首先运行服务端程序,再运行客户端程序。
0 0
- Windows 网络编程基于TCP协议的Socket通信
- 基于TCP协议的网络通信(socket编程)
- Linux网络编程之[基于socket通信的tcp协议的编程模型]
- Java基于TCP/IP协议的Socket网络通信详解
- 基于TCP协议的网络编程--socket编程(1)
- 基于TCP协议的网络编程--socket编程(2)
- Socket编程基础--基于TCP协议的网络编程
- 基于TCP/IP协议的网络编程—Socket编程
- Socket网络编程:基于TCP多线程通信
- socket编程-- 基于TCP协议的网络程序
- socket编程-- 基于TCP协议的网络程序
- socket编程-- 基于TCP协议的网络程序
- 基于TCP协议的Socket通信
- 基于TCP协议的Socket通信
- 基于TCP协议的Socket通信
- 基于TCP协议的socket通信
- Java网络编程笔记(三):点对点通信(Socket基于TCP协议)
- Java网络编程笔记(四):点对面通信(Socket基于TCP/IP)协议
- android 系统桌面设置为背景的方法
- CSP考试 2017年3月第2题 学生排队 C++实现
- JVM配置参数
- 蓝桥杯JAVA 十六进制转十进制
- Google开源JPEG压缩算法--Guetzli体验
- Windows 网络编程基于TCP协议的Socket通信
- Testflight上的版本更新
- 整数用pow要小心啊。。
- 认识和修改在Linux中stat命令下出现的Access,Modify,Change三类时间
- spark 笔记
- CodeForces 598A Tricky Sum
- 继承:避免遮掩继承而来的名称
- 2015年普级组模拟试题 序列
- java实现指定格式(如3.1.1)两个版本号比较