windows下socket编程实现client和server双向通信
服务端代码server.c
// server.cpp : Defines the entry point for the console application.
// #include <stdio.h>
#include <Winsock2.h> //Socket的函数调用
#include <windows.h> #define BUF_SIZE 6400 // 缓冲区大小 #pragma comment (lib, "ws2_32") // 使用WINSOCK2.H时,则需要库文件WS2_32.LIB DWORD WINAPI Rcv( LPVOID lpParam )
{
SOCKET sClient = *(SOCKET*)lpParam;
int retVal;
char bufRecv[BUF_SIZE];
memset( bufRecv, 0, sizeof( bufRecv ) );
while(1)
{
retVal = recv( sClient, bufRecv, BUF_SIZE, 0 );
if ( retVal == SOCKET_ERROR ) {
printf( "recive faild!\n" );
break;
} else {
printf( "收到客户端消息:%s\n", bufRecv );
}
}
return 0;
} DWORD WINAPI Snd( LPVOID lpParam )
{
SOCKET sClient = *(SOCKET*)lpParam;
int retVal;
char bufSend[BUF_SIZE];
memset( bufSend, 0, sizeof( bufSend ) );
while(1)
{
gets( bufSend );
retVal = send( sClient, bufSend, strlen(bufSend)+sizeof(char), 0 );
if ( retVal == SOCKET_ERROR ) {
printf( "send faild!\n" );
break;
}
}
return 0;
} int main(int argc, char* argv[])
{
// 初始化套接字动态库
WSADATA wsaData;
if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0 ) {
printf( "winsock load faild!\n" );
return 1;
} // 创建服务段套接字
SOCKET sServer = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( sServer == INVALID_SOCKET ) {
printf( "socket faild!\n" );
WSACleanup();
return -1;
} // 服务端地址
sockaddr_in addrServ; addrServ.sin_family = AF_INET;
addrServ.sin_port = htons( 9999 );
addrServ.sin_addr.s_addr = htonl( INADDR_ANY ); // 绑定套接字
if ( bind( sServer, ( const struct sockaddr* )&addrServ, sizeof(addrServ) ) == SOCKET_ERROR ) {
printf( "bind faild!\n" );
closesocket( sServer );
WSACleanup();
return -1;
} printf("Server is On IP:[%s],port:[%d]\n",inet_ntoa(addrServ.sin_addr),ntohs(addrServ.sin_port)); // 监听套接字 数字表示最多能监听客户个数
if ( listen( sServer, 5 ) == SOCKET_ERROR ) {
printf( "listen faild!\n" );
closesocket( sServer );
WSACleanup();
return -1;
} SOCKET sClient; // 客户端套接字 sockaddr_in addrClient;
int addrClientLen = sizeof( addrClient ); sClient = accept( sServer, ( sockaddr FAR* )&addrClient, &addrClientLen );
if ( sClient == INVALID_SOCKET ) {
printf( "accept faild!\n" );
closesocket( sServer );
WSACleanup();
return -1;
}
printf("accepted client IP:[%s],port:[%d]\n",inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port)); HANDLE hThread1, hThread2;
DWORD dwThreadId1, dwThreadId2; hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID*)&sClient, 0, &dwThreadId1);
hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID*)&sClient, 0, &dwThreadId2); ::WaitForSingleObject(hThread1, INFINITE);
::WaitForSingleObject(hThread2, INFINITE);
::CloseHandle(hThread1);
::CloseHandle(hThread2); closesocket( sClient );
WSACleanup(); // 资源释放 return 0;
}
客户端代码client.c
// client.cpp : Defines the entry point for the console application.
// #include <stdio.h>
#include <Winsock2.h> //Socket的函数调用
#include <windows.h> #define BUF_SIZE 6400 #pragma comment (lib, "ws2_32") // 使用WINSOCK2.H时,则需要库文件WS2_32.LIB DWORD WINAPI Rcv( LPVOID lpParam )
{
SOCKET sHost = *(SOCKET*)lpParam;
int retVal;
char bufRecv[BUF_SIZE];
memset( bufRecv, 0, sizeof( bufRecv ) );
while(1)
{
retVal = recv( sHost, bufRecv, BUF_SIZE, 0 );
if ( retVal == SOCKET_ERROR ) {
printf( "recive faild!\n" );
break;
} else {
printf( "收到服务器消息:%s\n", bufRecv );
}
}
return 0;
} DWORD WINAPI Snd( LPVOID lpParam )
{
SOCKET sHost = *(SOCKET*)lpParam;
int retVal;
char bufSend[BUF_SIZE];
memset( bufSend, 0, sizeof( bufSend ) );
while(1)
{
gets( bufSend );
retVal = send( sHost, bufSend, strlen(bufSend)+sizeof(char), 0 );
if ( retVal == SOCKET_ERROR ) {
printf( "send faild!\n" );
break;
}
}
return 0;
} int main(int argc, char* argv[])
{
WSADATA wsaData;
if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 ) {
printf( "Winsock load faild!\n" );
return 1;
} // 服务器套接字
SOCKET sHost = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( sHost == INVALID_SOCKET ) {
printf( "socket faild!\n" );
WSACleanup();
return -1;
} SOCKADDR_IN servAddr;
servAddr.sin_family = AF_INET;
// 注意 当把客户端程序发到别人的电脑时 此处IP需改为服务器所在电脑的IP
servAddr.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );
servAddr.sin_port = htons( 9999 ); // 连接服务器
if ( connect( sHost, (LPSOCKADDR)&servAddr, sizeof( servAddr ) ) == SOCKET_ERROR ) {
printf( "connect faild!\n" );
closesocket(sHost);
WSACleanup();
return -1;
}
printf("连接到服务器 IP:[%s],port:[%d]\n",inet_ntoa(servAddr.sin_addr),ntohs(servAddr.sin_port)); HANDLE hThread1, hThread2;
DWORD dwThreadId1, dwThreadId2; hThread1 = ::CreateThread( NULL, NULL, Snd, (LPVOID)&sHost, 0, &dwThreadId1 );
hThread2 = ::CreateThread( NULL, NULL, Rcv, (LPVOID)&sHost, 0, &dwThreadId2 ); ::WaitForSingleObject( hThread1, INFINITE );
::WaitForSingleObject( hThread2, INFINITE );
::CloseHandle(hThread1);
::CloseHandle(hThread2); closesocket(sHost);
WSACleanup();
return 0;
}
截图如下:编译好后首先是启动服务端(来监听),然后再启动客户端

windows下socket编程实现client和server双向通信的更多相关文章
- windows下socket编程:区分shutdown()及closesocket()
以下描述主要是针对windows平台下的TCP socket而言. 首先需要区分一下关闭socket和关闭TCP连接的区别,关闭TCP连接是指TCP协议层的东西,就是两个TCP端之间交换了一些协议包( ...
- linux下socket编程实例
linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...
- Windows 下用 gogs 配置局域网 git server
大道曙光 Windows 下用 gogs 配置局域网 git server 最近要用 C# 开发一个新的项目,所以需要在 Windows 局域网环境下构建一个 git server. 在 Window ...
- 初尝Windows 下批处理编程
本文叫“ 初尝Windows 下批处理编程”是为了延续上一篇“初尝 Perl”,其实对于博主而言批处理以及批处理编程早就接触过了. 本文包括以下内容 1.什么是批处理 2.常用批处理命令 3.简介批处 ...
- Linux下Socket编程的端口问题( Bind error: Address already in use )
Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误 ...
- 初探WINDOWS下IME编程
初探WINDOWS下IME编程作者:广东南海市昭信科技有限公司-李建国 大家知道,DELPHI许多控件有IME属性.这么好用的东西VC可没自带,怎么办呢?其实,可通过注册表,用API实现.下面说一下本 ...
- Windows下串口编程
造冰箱的大熊猫@cnblogs 2019/1/27 将Windows下串口编程相关信息进行下简单小结,以备后用. 1.打开串口 打开串口使用CreateFile()函数.以打开COM6为例: HAN ...
- Linux下socket编程基本知识
本文档主要讲解了Linux下socket编程的一些基本知识,主要包括套接字和字节序的概念,以及一些常用的结构体和函数. 本文是在网易云课堂学习过程中的记录,这个老师讲得很不错,推荐大家围观. Linu ...
- 一个linux下socket编程的例子,client连server
关于socket编程,以下文章写得比较好:http://www.cnblogs.com/xudong-bupt/archive/2013/12/29/3483059.html 1. accept()函 ...
随机推荐
- HMAC算法原理
HMAC算法是一种基于密钥的报文完整性的验证方法 ,其安全性是建立在Hash加密算法基础上的.它要求通信双方共享密钥.约定算法.对报文进行Hash运算,形成固定长度的认证码.通信双方通过认证码的校验来 ...
- 机器学习之TensorFlow介绍
TensorFlow的概念很简单:使用python定义一个计算图,然后TensorFlow根据计算图生成高性能的c++代码. 如上图所示,使用图的方式实现了函数\(f(x,y)=x^2y+y+2\)的 ...
- Neo4j 第八篇:投射和过滤
投射子句用于定义如何返回数据集,并可以对返回的表达式设置别名,而过滤子句用于对查询的结果集按照条件进行过滤 一,Return子句 使用return子句返回节点,关系和关系. 1,返回节点 MATCH ...
- R数据挖掘 第二篇:基于距离评估数据的相似性和相异性
聚类分析根据对象之间的相异程度,把对象分成多个簇,簇是数据对象的集合,聚类分析使得同一个簇中的对象相似,而与其他簇中的对象相异.相似性和相异性(dissimilarity)是根据数据对象的属性值评估的 ...
- KVM虚拟机典型配置文件xml
<domain type='kvm'> <name>vm64-1</name> //虚拟机名称 <memory unit='MiB'>2300</ ...
- C# 中 ==和equals的区别
不想说太多,直接上代码,这两个就没什么联系,有自己独立的规则.联系在一起其实不利于记忆. 下面是测试代码 Console.WriteLine("--equals和==的区别--") ...
- Jenkins的使用(二)-------MSBuild
六.构建 左边菜单栏 Manage Jenkins --->ManagePlugins--->可选插件,然后搜索 MSBuild,并安装 添加ssh插件后新增了两种 1.使用MSBu ...
- C# winform中组合键奇怪不响应问题
再winform中使用ProcessCmdKey处理快捷键响应,针对单一快捷键响应没有任何问题.但是针对组合键总是无法响应,如下: protected override bool ProcessCmd ...
- python每日经典算法题5(基础题)+1(较难题)
一:基础算法题5道 1.阿姆斯特朗数 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数.判断用户输入的数字是否为阿姆斯特朗数. (1)题目分析:这里要先得到该数是多少位的,然后再把 ...
- C++中的Point类与vector类的简单处理
首先设计Vector与Point的表示方法,再依次完善两个类中的构造函数,复制构造函数等. 向量由两个点表示,当进行运算的时候,转化起点坐标为(0,0): 第14行:由于Vector需要用到Point ...