使用TCP/IP协议实现客户端和服务端全双工通信(转载)
来源:互联网 发布:宝软网java破解游戏 编辑:程序博客网 时间:2024/06/04 23:16
(一)
在基于UDP的程序中,你有没有想过,如果我的这台主机在通讯的时候要求既能够收到别的主机发来的数据,又能够自己向目的主机发出数据,该怎样实现?也就是说需要两个while循环同时进行。答案是使用多线程,一个线程用于接受数据,另一个线程用来发送数据。接下来我们介绍WinSock的多线程编程。
多线程的实现我们使用_beginthread()函数:
uintptr_t _beginthread( void( *start_address )( void * ), unsigned stack_size, void *arglist );
第一个参数是一个函数指针,这个 自己定义的函数返回类型是void,参数是void*;
第二个参数是申请的内存空间,缺省(0)是1M,或者1024*1024,是一样的;
第三个参数是要传递的参数。
如图:不同的线程使用的栈是不一样的,所以两个进程中的int n是不一样的。但是这两个进程所用的栈空间是在系统的栈空间中线性存放的。
//Multi-UCP-Server #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <iostream> #include <process.h> #include <string> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; const int PORT = 8009; void RecvMain(void *p) { sockaddr_in sfrom = { 0 }; //返回用 int slen = sizeof(sfrom); SOCKET sock = (SOCKET)p; //void*转换回来 char s[1024]; int n = 0; while ((n = recvfrom(sock, s, sizeof(s), 0,(sockaddr*)&sfrom,&slen)) > 0) { s[n] = '\0'; cout << inet_ntoa(sfrom.sin_addr) << "-" << htons(sfrom.sin_port) << ":" << s << endl << endl; } } int main() { int n; WSADATA wd; n = WSAStartup(MAKEWORD(2, 2), &wd); if (n) { cout << "WSAStartup函数错误!" << endl; return -1; } SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); if (INVALID_SOCKET == sock) { cout << "socket建立失败!" << endl; cout << "错误码是:" << WSAGetLastError() << endl; return -1; } sockaddr_in sa = { AF_INET, htons(PORT) }; n = bind(sock, (sockaddr*)&sa, sizeof(sa)); if (n == SOCKET_ERROR) { cout << "bind绑定端口失败!" << endl; cout << "错误码是:" << WSAGetLastError() << endl; return -1; } else { cout << "端口发布成功:" << PORT << endl; } _beginthread(RecvMain, 1024 * 1024, (void*)sock); char s[256] = { 0 }; char sIP[20]; while (true) { cout << "请输入对方的IP地址:"; //(1) cin >> sIP; cout << "请输入要发送的内容:"; fflush(stdin); gets(s); sa.sin_addr.S_un.S_addr = inet_addr(sIP); sa.sin_port = htons(PORT); sendto(sock, s, strlen(s), 0, (sockaddr*)&sa, sizeof(sa)); Sleep(16); //保证先打印数据,防止(1)处的交替进程干扰 } return 0; }
(二)
在基于TCP的程序中,如果我们的这台主机想要同时接收多台主机发来的信息时,我们该怎样实现呢?也就是说多个通讯同时进行,答案当然还是多线程。并且实现方式和基于UDP的是一样的,我们都采用_beginthread函数实现。
另外,对于程序中的accept函数,如果我们并不需要获取连接方的ip地址和端口信息时,那么第二三个参数都是可以缺省的,置为NULL。但是如果我们想获取连接方的信息时,那么要先定义一个sockaddr_in 对象,并且强制转换成sockaddr*类型传进参数,这点注意即可。
//Multi-TCP-Server #include <cstdio> #include <iostream> #include <process.h> #include <string> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; const int PORT = 8009; void recvProc(void *p) { SOCKET socka = (SOCKET)p; //void*转换回来 char s[1024]; int n = 0; while ((n = recv(socka, s, sizeof(s), 0)) > 0) { s[n] = '\0'; cout << s << endl; } } int main() { int n; WSADATA wd; n = WSAStartup(MAKEWORD(2, 2), &wd); if (n) { cout << "WSAStartup函数错误!" << endl; return -1; } SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == sock) { cout << "socket建立失败!" << endl; cout << "错误码是:" << WSAGetLastError() << endl; return -1; } sockaddr_in sa = { AF_INET, htons(PORT) }; n = bind(sock, (sockaddr*)&sa, sizeof(sa)); if (n == SOCKET_ERROR) { cout << "bind绑定端口失败!" << endl; cout << "错误码是:" << WSAGetLastError() << endl; return -1; } else { cout << "端口发布成功:" << PORT << endl; } listen(sock, 5); //第二个参数一般设置5 char s[256] = { 0 }; while (true) { SOCKET socka = accept(sock, NULL, NULL); //第二三个参数是连接者的ip和端口等信息,是返回类型的值,不需要可以置null _beginthread(recvProc, 0, (void*)socka); //void*指向任何类型的指针 } return 0; }
阅读全文
0 0
- 使用TCP/IP协议实现客户端和服务端全双工通信(转载)
- Socket TCP 协议实现服务端和客户端的简单通信
- 基于TCP协议实现客户服务器的全双工通信
- Android-使用TCP/IP协议实现断点上传(客户端-服务端代码)(+0)
- C# Tcp 全双工通信 实现
- Android--使用TCP/IP协议实现断点上传(客户端-服务端代码)
- Java Websocket实例【服务端与客户端实现全双工通讯】
- java客户端与服务端通信Tcp/Ip
- C语言实现服务端和客户端进行TCP通信实例
- Java简单实现TCP服务端和客户端通信
- C语言实现服务端和客户端进行TCP通信实例
- 全双工实现服务器与客户端的通信
- 使用VC++实现 客户端和服务端通信 获取本机IP地址
- 通过TCP/IP协议进行客户端与服务端的通信C/C++
- WebSoket 全双工通信的应用协议理解和实例
- 客户端与服务端的TCP通信实现(Qt)
- linux网络编程之用socket实现简单客户端和服务端的通信(基于TCP)
- TCP的客户端和服务端通信
- c随机函数
- 在Modelsim仿真时出现的dirctory未找到或者出现error:in read mode
- 创建maven项目
- JVM类加载机制
- GDI
- 使用TCP/IP协议实现客户端和服务端全双工通信(转载)
- 使用PHP代码实现迪杰特斯拉算法
- FATE(HDU-2159)
- 设计模式学习笔记——简单工厂模式、工厂方法模式、抽象工厂模式
- 双向循环链表
- cocos 寻路 lua实现
- 一个关于数据库迁移的小错误
- Altera Modelsim仿真sim模板
- 暴力——BZOJ2783/Luogu3252 [JLOI2012]树