多线程套接字编程-----程序实例(C 实现)

合集下载

C语言网络编程套接字和常用协议

C语言网络编程套接字和常用协议

C语言网络编程套接字和常用协议网络编程是现代计算机科学中非常重要的一个领域,通过网络编程可以实现不同设备之间的数据传输与通信。

C语言作为一种强大的编程语言,在网络编程方面也有着广泛的应用。

本文将介绍C语言网络编程中常用的套接字和协议。

一、套接字(Socket)基础概念套接字是计算机网络中进行网络通信的一种方式,可以看做是网络中两个应用程序之间的一个端点。

套接字使用IP地址和端口号来唯一标识一个通信节点。

在C语言中,套接字相关的操作需要通过系统调用函数来实现。

1. 创建套接字在C语言中,创建套接字需要使用socket()函数,该函数返回一个套接字描述符,可以用于后续的通信操作。

常见的套接字类型包括流套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM)等。

2. 绑定套接字绑定套接字可以将套接字地址和具体的IP地址以及端口号关联起来,从而能够监听特定的网络地址。

在C语言中,可以使用bind()函数来绑定套接字。

3. 监听连接如果希望接受其他应用程序的连接请求,可以使用listen()函数来监听特定的套接字。

4. 接受连接一旦有连接请求到达监听套接字,可以使用accept()函数来接受连接请求,返回一个新的套接字描述符,用于与客户端进行通信。

5. 发起连接如果希望主动向其他应用程序发起连接请求,可以使用connect()函数来建立连接。

6. 数据传输已建立连接的套接字可以通过read()和write()等函数进行数据的读取和写入操作,实现数据的传输。

二、网络协议在网络编程中,协议起到了关键的作用,它定义了数据的传输方式、格式和规则,确保网络通信的可靠性和正确性。

下面是常用的网络协议:1. TCP/IP协议TCP/IP协议是互联网上最常用的协议之一,它基于TCP传输协议和IP网络协议。

TCP协议提供了一种可靠的数据传输方式,确保数据的有序、完整、无差错地传输;而IP协议则负责数据在网络中的传输。

C#多线程编程实战(一):线程基础

C#多线程编程实战(一):线程基础

C#多线程编程实战(⼀):线程基础1.1 简介为了防⽌⼀个应⽤程序控制CPU⽽导致其他应⽤程序和操作系统本⾝永远被挂起这⼀可能情况,操作系统不得不使⽤某种⽅式将物理计算分割为⼀些虚拟的进程,并给予每个执⾏程序⼀定量的计算能⼒。

此外操作系统必须始终能够优先访问CPU,并能调整不同程序访问CPU的优先级。

线程正式这⼀慨念的实现。

多线程优点:可以同时执⾏多个计算任务,有可能提⾼计算机的处理能⼒,使得计算机每秒能执⾏越来越多的命令多线程缺点:消耗⼤量的操作系统资源。

多个线程共享⼀个处理器将导致操作系统忙于管理这些线程,⽽⽆法运⾏程序。

1.2 创建线程using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Thread t1 = new Thread(new ThreadStart(PrintNumbers));//⽆参数的委托t1.Start();Thread t2 = new Thread(new ParameterizedThreadStart(PrintNumbers));//有参数的委托t2.Start(10);Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}//注意:要使⽤ParameterizedThreadStart,定义的参数必须为objectstatic void PrintNumbers(object count){Console.WriteLine("Starting...");for (int i = 0; i < Convert.ToInt32(count); i++){Console.WriteLine(i);}}}}注释:我们只需指定在不同线程运⾏的⽅法名,⽽C#编译器会在后台创建这些对象1.3 暂停线程using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Thread t1 = new Thread(PrintNumbersWithDelay);t1.Start();PrintNumbers();Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}static void PrintNumbersWithDelay(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}}}注释:使⽤Thread.Sleep(TimeSpan.FromSeconds(2));暂停线程1.4 线程等待using System;namespace MulityThreadNote{class Program{static void Main(string[] args){Console.WriteLine("Starting...");Thread t = new Thread(PrintNumbersWithDelay);t.Start();t.Join(); //使⽤Join等待t完成PrintNumbers();Console.WriteLine("THread Complete");Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}static void PrintNumbersWithDelay(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}}}注释:使⽤t.Join(); 等待t完成1.5 终⽌线程using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Console.WriteLine("Starting Program...");Thread t1 = new Thread(PrintNumbersWithDelay);t1.Start();Thread.Sleep(TimeSpan.FromSeconds(6));t1.Abort(); //使⽤Abort()终⽌线程Console.WriteLine("Thread t1 has been aborted");Thread t2 = new Thread(PrintNumbers);PrintNumbers();Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}static void PrintNumbersWithDelay(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}}}注释:使⽤Thread实例的Abort⽅法终⽌线程1.6 检测线程状态using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Console.WriteLine("Start Program...");Thread t1 = new Thread(PrintNumbersWithStatus);Thread t2 = new Thread(DoNothing);Console.WriteLine(t1.ThreadState.ToString());//获取实例线程状态 t2.Start();t1.Start();for (int i = 0; i < 30; i++)}Thread.Sleep(TimeSpan.FromSeconds(6));t1.Abort();Console.WriteLine("thread t1 has been aborted");Console.WriteLine(t1.ThreadState.ToString());Console.WriteLine(t2.ThreadState.ToString());Console.ReadLine();}private static void PrintNumbersWithStatus(){Console.WriteLine("Starting...");Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());//获取当前线程状态for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}private static void DoNothing(){Thread.Sleep(TimeSpan.FromSeconds(2));}}}注释:使⽤Thread.ThreadState获取线程的运⾏状态。

使用VC++的网络编程总结

使用VC++的网络编程总结

客户机
创建并初始化套接字
图4 数据报套接字 (无 连 接 通 信 )编 程
“有序”指数据包按发送的顺序送达。“ 不重复”指一个特定的数据包只能获取一次。这两 种套接字都是双向的,是可以同时在两个方向上(全双工)进行通信的数据流。 注意 在某些网络协议下(如 XNS) ,流可以面向记录,即作为记录流而非字节流。 但 在更常用的 TCP/IP 协议下,流为字节流。Windows Sockets 提供与基础协议无关的抽象化 级别。 1.3.3 套接字的作用 套接字的作用非常大,至少在下面三种通信上下文中如此: � 客户端/服务器模型。 � 对等网络方案,如聊天应用程序。 � 通过让接收应用程序将消息解释为函数调用来进行远程过程调用 (RPC)。 1.3.4 端口与地址 在网络上,一个套接字的标识主要借助于地址和端口来描述。 套接字的地址指该套接字所在计算机的网络地址, 可以为域名或 IP 地址的形式。 通常, 创建套接字时不必指明网络地址, 只有在拥有多个网络地址的机器时, 才需要显式指定一个 网络地址。 同一机器上可以运行多个网络应用程序,每个应用程序都有自己的套接字用以进行网 络通信,此时如果只有地址标识套接字,则当一个通信包到达机器时,将无法确定究竟是哪
客户机
创建并初始化套接字
图3 流式套接字 ( 有连接通信 )编 程
1.3.2.2 数据报套接字 数据报套接字支持面向记录的数据流,但不能确保能被送达,也无法确保按照发送顺 序或不重复。
服务器
创建并初始化套接字 监听来自客户机的请求 向服务器发出请求 进行处理 发送结果给客户端 接收结果 关闭连接 关闭连接
LPWSADATA lpWSAData
//指向数据结构 WSDATA 的指针, //得到 window下: typedef struct WSAData { WORD wVersion; WORD wHighVersion; #ifdef _WIN64 unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; #else char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; #endif } WSADATA, FAR * LPWSADATA; 2)WSACleanup 结束对 Windows Sockets DLL 的调用 函数原型:int WSACleanup(void); 3)socket 用于建立 Sockets。 函数原型:SOCKET socket( int af, //地址族,一般是 AF_INET int type , //socket 类型,SOCK_STREAM 或 SOCK_DGRAM int protocol //协议类型,通常取值 0 ); 4)closesocket 关闭套接字 函数原型:int closesocket( SOCKET s //要关闭的套接字 ); 5)bind 将一个本地地址和一个 SOCKET 描述字连接起来 函数原型:int bind( SOCKET s, //要绑定的套接字 const struct sockaddr FAR* name, //指向 SOCKADDR 结构的地址 int namelen //地址结构的 sizeof ) Tcp/ip SOCKADDR 结构 struct sockaddr{ unsigned short sa_family; char sa_data[4]; };

基于UDP的socket程序,多线程操作,windows下C语言

基于UDP的socket程序,多线程操作,windows下C语言

char recvBuf[50]="\0";
int len=sizeof(SOCKADDR);
sockaddr_in addrClient;
while(1)
{
recvfrom(s,recvBuf,50,0,(SOCKADDR*)&addrClient,&len);
printf("他:\n %s\n",recvBuf);
#include <Winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
DWORD WINAPI ThreadProc(LPVOID lpParameter) //次线程,发消息
tcpaddr2.sin_family=AF_INET;
tcpaddr2.sin_port=htons(5050); //发送端口5050
tcpaddr2.sin_addr.S_un.S_addr=inet_addr(ip);
int len=sizeof(SOCKADDR);
while(1)
{
printf("请输入服务端ip地址:");//程序接收端
char ip[16]="\0";
scanf("%s",ip);
//创建socket2
SOCKET s2=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

c 多线程实现的四种方式

c 多线程实现的四种方式

c 多线程实现的四种方式C语言是一种非常流行的编程语言,它可以用来实现多线程编程。

多线程编程可以让你的程序更高效、更快速地运行,因为它可以同时执行多个任务。

在这篇文章中,我们将介绍 C 多线程实现的四种方式。

1. 使用 pthread 库pthread 是一个 POSIX 标准定义的多线程库,它提供了一套API 接口,可以用来实现多线程编程。

使用 pthread,你可以创建多个线程并且控制它们的行为。

这种方式是 C 语言实现多线程的最常用方式之一。

2. 使用 OpenMP 库OpenMP 是一个开源的多线程库,它可以用来在 C 语言中实现多线程编程。

OpenMP 提供了一套 API 接口,可以让你更方便地编写并行程序。

使用 OpenMP,你可以使用 #pragma 指令来控制并行执行的代码块。

3. 使用 POSIX 线程POSIX 线程是一种 POSIX 标准定义的多线程接口,它可以用来实现多线程编程。

与 pthread 类似,POSIX 线程提供了一套 API 接口,可以让你更方便地编写多线程程序。

4. 使用 Windows 线程如果你在 Windows 操作系统上编写 C 语言程序,你可以使用Windows 线程来实现多线程编程。

Windows 线程提供了一套 API 接口,可以让你在 Windows 平台上创建多个线程并且控制它们的行为。

总结以上是 C 多线程实现的四种方式。

在选择使用哪种方式时,你应该考虑自己的需求和使用的操作系统。

不同的方式会有不同的 API 接口、性能和可移植性。

如果你需要了解更多关于 C 多线程编程的知识,可以参考相关的书籍和教程。

linux下的CC++多进程多线程编程实例详解

linux下的CC++多进程多线程编程实例详解

linux下的CC++多进程多线程编程实例详解linux下的C\C++多进程多线程编程实例详解1、多进程编程#include <stdlib.h>#include <sys/types.h>#include <unistd.h>int main(){pid_t child_pid;/* 创建⼀个⼦进程 */child_pid = fork();if(child_pid == 0){printf("child pid\n");exit(0);}else{printf("father pid\n");sleep(60);}return 0;}2、多线程编程#include <stdio.h>#include <pthread.h>struct char_print_params{char character;int count;};void *char_print(void *parameters){struct char_print_params *p = (struct char_print_params *)parameters;int i;for(i = 0; i < p->count; i++){fputc(p->character,stderr);}return NULL;}int main(){pthread_t thread1_id;pthread_t thread2_id;struct char_print_params thread1_args;struct char_print_params thread2_args;thread1_args.character = 'x';thread1_args.count = 3000;pthread_create(&thread1_id, NULL, &char_print, &thread1_args);thread2_args.character = 'o';thread2_args.count = 2000;pthread_create(&thread2_id, NULL, &char_print, &thread2_args);pthread_join(thread1_id, NULL);pthread_join(thread2_id, NULL);return 0;}3、线程同步与互斥1)、互斥pthread_mutex_t mutex;pthread_mutex_init(&mutex, NULL);/*也可以⽤下⾯的⽅式初始化*/pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex);/* 互斥 */thread_flag = value;pthread_mutex_unlock(&mutex);2)、条件变量int thread_flag = 0;pthread_mutex_t mutex;pthread_cond_t thread_flag_cv;\void init_flag(){pthread_mutex_init(&mutex, NULL);pthread_cond_init(&thread_flag_cv, NULL);thread_flag = 0;}void *thread_function(void *thread_flag){while(1){pthread_mutex_lock(&mutex);while(thread_flag != 0 ){pthread_cond_wait(&thread_flag_cv, &mutex);}pthread_mutex_unlock(&mutex);do_work();}return NULL;}void set_thread_flag(int flag_value){pthread_mutex_lock(&mutex);thread_flag = flag_value;pthread_cond_signal(&thread_flag_cv);pthread_mutex_unlock(&mutex);}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

C语言socket编程----实现UDP通信

C语言socket编程----实现UDP通信

C语⾔socket编程----实现UDP通信TCP/IP协议叫做传输控制/⽹际协议,⼜叫做⽹络通信协议。

实际上,它包括上百个功能的协议。

套接字(socket):在⽹络中⽤来描述计算机中不同程序与其他计算程序的通信⽅式。

套接字分为三类;流式socket(SOCK_STREAM):提供可靠,⾯向连接的通信流;它使⽤TCP协议,从⽽保证了数据传输的正确性和顺序性。

数据报socket(SOCK_DGRAM):数据报套接字定义了⼀种⽆连接的服务,数据通过相互独⽴的报⽂进⾏传输,⽆序的,并且不保证可靠,⽆差错的。

它使⽤的数据报协议是UDP。

原始socket:原始套接字允许对底层协议如TP或ICMP进⾏直接访问,它功能强⼤但使⽤复杂,主要⽤于⼀些协议的开发。

下⾯是UDP通信的demo://socket udp 服务端1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 #include<sys/socket.h>5 #include<arpa/inet.h>67int main()8 {9//创建socket对象10int sockfd=socket(AF_INET,SOCK_DGRAM,0);1112//创建⽹络通信对象13struct sockaddr_in addr;14 addr.sin_family =AF_INET;15 addr.sin_port =htons(1324);16 addr.sin_addr.s_addr=inet_addr("127.0.0.1");1718//绑定socket对象与通信链接19int ret =bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));20if(0>ret)21 {22 printf("bind\n");23return -1;2425 }26struct sockaddr_in cli;27 socklen_t len=sizeof(cli);2829while(1)30 {31char buf =0;32 recvfrom(sockfd,&buf,sizeof(buf),0,(struct sockaddr*)&cli,&len);33 printf("recv num =%hhd\n",buf);3435 buf =66;36 sendto(sockfd,&buf,sizeof(buf),0,(struct sockaddr*)&cli,len);3738 }39 close(sockfd);4041 }//socket udp 客户端1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/socket.h>4 #include<unistd.h>5 #include<arpa/inet.h>67int main()8 {9//创建socket对象10int sockfd=socket(AF_INET,SOCK_DGRAM,0);1112//创建⽹络通信对象13struct sockaddr_in addr;14 addr.sin_family =AF_INET;15 addr.sin_port =htons(1324);16 addr.sin_addr.s_addr = inet_addr("192.168.0.143");1718while(1)19 {20 printf("请输⼊⼀个数字:");21char buf=0;22 scanf("%hhd",&buf);23 sendto(sockfd,&buf,24sizeof(buf),0,(struct sockaddr*)&addr,sizeof(addr));2526 socklen_t len=sizeof(addr);27 recvfrom(sockfd,&buf,sizeof(buf),0,(struct sockaddr*)&addr,&len); 2829if(66 ==buf)30 {31 printf(" server 成功接受\n");32 }33else34 {35 printf("server 数据丢失\n");36 }3738 }39 close(sockfd);4041 }。

C语言网络编程详解

C语言网络编程详解

C语言网络编程详解网络编程是计算机科学中的重要领域,而C语言作为一种广泛使用的编程语言,也在网络编程中扮演着重要的角色。

本文将详细介绍C 语言网络编程的相关知识和技巧,帮助读者更好地理解和应用该领域的知识。

1. 网络编程概述网络编程是指利用计算机网络进行程序开发和通信的过程。

它主要涉及到数据传输、网络协议、套接字等概念。

C语言提供了一系列函数和库来支持网络编程,如socket函数、bind函数、listen函数等。

2. 套接字编程套接字(socket)是进行网络通信的一种机制。

C语言提供了一组函数用于创建、设置和管理套接字。

通过使用这些函数,我们可以建立起客户端和服务器之间的通信连接,实现数据的收发和传输。

2.1 套接字基础在进行网络编程之前,我们需要了解基本的套接字概念和操作。

首先,我们需要创建一个套接字,可以是TCP套接字或者UDP套接字。

然后,我们可以使用bind函数将套接字与IP地址和端口号绑定。

接下来,我们可以使用listen函数开始监听来自客户端的连接请求。

2.2 TCP编程TCP(传输控制协议)是一种可靠的连接协议,适用于需要保证数据可靠传输的场景。

在C语言中,我们可以使用socket函数创建一个TCP套接字。

然后,通过accept函数接受来自客户端的连接请求,使用send和recv函数进行数据的发送和接收。

2.3 UDP编程UDP(用户数据报协议)是一种无连接的协议,适用于需要快速传输数据的场景。

在C语言中,我们可以使用socket函数创建一个UDP 套接字。

与TCP不同的是,UDP不需要先建立连接,可以直接使用sendto和recvfrom函数进行数据的发送和接收。

3. 网络编程实例为了更好地理解和应用C语言网络编程,下面将通过两个实例来演示TCP和UDP编程的基本过程。

3.1 TCP编程实例假设我们要实现一个简单的聊天室程序,服务器接收来自不同客户端的消息,并转发给其他客户端。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

多线程套接字编程-----程序实例(C++实现)多线程套接字编程-----程序实例(C++实现)标签:多线程编程c++structsocket网络2012-04-12 12:54 9921人阅读评论(1) 收藏举报分类:C/C++(18)网络版权声明:本文为博主原创文章,未经博主允许不得转载。

一.程序介绍该程序主要包括以下内容:1.多线程程序设计的一般框架,新线程负责循环接收网络数据,一旦收到网络数据就交由主线程处理;主线程负责循环处理网络数据。

2.(UDP)套接字编程的一般框架,为了方便实验该程序只是用到了UDP 套接字,没有考虑丢包延迟等网络问题,在实际程序设计中可以采用TCP套接字。

3.如何使用套接字发送多个不同的结构体,通过对不同的结构体添加不同的标志位,从而区分不同的结构体类型。

该程序的默认设置为:1.各参与者IP地址为127.0.0.1(环回地址,用于单机测试)。

2.编号为i的参与者端口号为10000+i,例如,编号为1的参与者其端口号为10001。

由于是采取多机测试,所以每个进程的IP地址都是127.0.0.1,所以需要使用不同的端口,从而区分出不同的进程,这样才能保证网络数据发送到正确的参与者处理。

3.编号为1的参与者向编号为2的参与者发送测试数据。

编号为1的参与者向2发送三个不同的结构体,参与者2收到后首先提取结构体的标志位,然后确定用何种结构体变量来接收网络数据。

提取到正确的结构体后,打印结构体中的数据。

二.程序源码1.Node.h[plain] view plain copy#ifndef NORMALNODE #define NORMALNODE #include "winsock.h" #include "windows.h" #include&lt;iostream&gt; #include &lt;string&gt; using namespace std; constWM_PARTY_MSG=WM_USER+1; struct m_struct1 { int flag; char Value1[15]; }; structm_struct2 { int flag; char Value1[15];char Value2[15]; }; struct m_struct3 { int flag; char Value1[15]; char Value2[15]; charValue3[15]; }; struct ThreadParameter { int Port; DWORD MainThreadID; }; class Node { private: int ID;//自身ID public: Node();~Node(); void StartMyThread(); int DealMessage(char *MyMessage,int MessageLength); static DWORD WINAPI StartAcceptThread(LPVOID lpData); int SendStruct(); int TransmitMessage(int ParticipatorID,char *StructBuffer,int BufferLength); }; #endif2.Node.cpp[plain] view plain copy#include "Node.h"const MSG_STRUCT1=1; const MSG_STRUCT2=2; const MSG_STRUCT3=3; Node::Node()//构造函数{ cout&lt;&lt;"******************************************** *******"&lt;&lt;endl; cout&lt;&lt;"\n该程序主要包括:\n"&lt;&lt;endl; cout&lt;&lt;"1.多线程套接字程序设计框架"&lt;&lt;endl; cout&lt;&lt;"2.利用套接字发送结构体的方法"&lt;&lt;endl; cout&lt;&lt;"3.多个不同结构体的发送和接收"&lt;&lt;endl; cout&lt;&lt;"\n默认设置为:\n"&lt;&lt;endl; cout&lt;&lt;"1.各参与者IP地址为127.0.0.1(环回地址,用于单机测试)"&lt;&lt;endl;cout&lt;&lt;"2.编号为i的参与者端口号为10000+i"&lt;&lt;endl; cout&lt;&lt;"3.编号为1的参与者向编号为2的参与者发送测试数据"&lt;&lt;endl;cout&lt;&lt;"***************************************************"&lt;&lt;endl; cout&lt;&lt;"输入编号:"&lt;&lt;endl;cin&gt;&gt;ID; } Node::~Node()//析构函数{ } void Node::StartMyThread()//启动新线程{ DWORD myMainThreadID=::GetCurrentThreadId(); //获取当前线程也就是主线程的ID号static ThreadParameter tp;//此处需设置为静态变量tp.MainThreadID=myMainThreadID;tp.Port=10000+ID;//端口号初始化HANDLE hThread=CreateThread(NULL,0,StartAcceptThread,(LPVOID)&amp ;tp,0,NULL);//创建新线程CloseHandle(hThread); } DWORD WINAPI Node::StartAcceptThread(LPVOID lpData)//线程的启动函数,用来循环接收来自参与者发来的轮消息{ ThreadParameter tp=*((ThreadParameter *)lpData); char RecveBuffer[20][4096];//为了保证,消息能够被安全处理,也就是在消息被线程处理之前,保证没有新的消息覆盖,我们定义了一个二维数组,相当于二十个缓冲区,用来接收数据for(int i=0;i&lt;20;i++) memset(RecveBuffer[i],0,4096); SOCKET RecveSocket = ::socket(AF_INET, SOCK_DGRAM, 0);//创建UDP套接字SOCKADDR_IN sin;sin.sin_family = AF_INET; sin.sin_addr.S_un.S_addr = INADDR_ANY; sin.sin_port = ::htons(tp.Port);//端口号设置if(::bind(RecveSocket,(sockaddr*)&amp;sin, sizeof(sin)) == SOCKET_ERROR)//地址与套接字绑定{ cout&lt;&lt;"套接字绑定错误!"&lt;&lt;endl; return 0; } /*以下是循环接收网络数据部分,在通信量大的时候,**可能数据不能及时传至主线程,而造成信息的覆盖**所以此处设置了一个二位数组RecveBuffer,相当于**20个长度为4096的缓冲区,可以适应通信量较大的情况。

*/ SOCKADDR_IN addrRemote; int nLen = sizeof(addrRemote); int recvcount=0;while(true) { if(recvcount==20)recvcount=0; //套接字接收函数int nRet = ::recvfrom(RecveSocket,RecveBuffer[recvcount],4096, 0,(sockaddr*)&amp;addrRemote, &amp;nLen);if(nRet==SOCKET_ERROR){ cout&lt;&lt;"接受错误!"&lt;&lt;endl;return 0; } if(nRet &gt; 0){ //收到网络数据以后向主线程发送消息,并将数据交由主线程处理if(PostThreadMessage(tp.MainThreadID,WM_PARTY_MS G,0,(LPARAM)RecveBuffer[recvcount])==0){ cout&lt;&lt;"向主线程发送消息失败"&lt;&lt;GetLastError()&lt;&lt;endl; } recvcount++; } } return 1; } //消息处理函数,该函数用处理不同的网络数据,对其进行分类响应int Node::DealMessage(char *MyMessage,int MessageLength) { int StrcutFlag; //获取网络数据的标志位,根据不同的标志位进行不同的处理memcpy(&amp;StrcutFlag,MyMessage,sizeof(StrcutFlag)); if(StrcutFlag==MSG_STRUCT1)//结构体1的数据{ m_struct1 ms1;memcpy(&amp;ms1,MyMessage,sizeof(ms1));//取出结构体1 cout&lt;&lt;ms1.Value1&lt;&lt;endl; } else if(StrcutFlag==MSG_STRUCT2)//结构体2的数据{ m_struct2 ms2;memcpy(&amp;ms2,MyMessage,sizeof(ms2));//取出结构体2 cout&lt;&lt;ms2.Value2&lt;&lt;endl; } else if(StrcutFlag==MSG_STRUCT3)//结构体3的数据{ m_struct3 ms3;memcpy(&amp;ms3,MyMessage,sizeof(ms3));//取出结构体3 cout&lt;&lt;ms3.Value3&lt;&lt;endl;return 0; } return 1; } //结构体发送函数int Node::SendStruct() { charbuf1[60],buf2[60],buf3[60]; if(ID!=1) return 0; //定义三种类型的结构体m_struct1 s1;m_struct2 s2; m_struct3 s3; //对不同的结构体进行不同的赋值s1.flag=1; strcpy(s1.Value1,"结构体1"); s2.flag=2; strcpy(s2.Value2,"结构体2"); s3.flag=3; strcpy(s3.Value3,"结构体3"); memset(buf1,0,60);memcpy(buf1,&amp;s1,sizeof(s1));//将结构体1送入char 数组,进行发送TransmitMessage(2,buf1,sizeof(s1));//发送结构体1cout&lt;&lt;"发送结构体1"&lt;&lt;endl;memset(buf2,0,60);memcpy(buf2,&amp;s2,sizeof(s2));//将结构体2送入char 数组,进行发送TransmitMessage(2,buf2,sizeof(s2));//发送结构体2cout&lt;&lt;"发送结构体2"&lt;&lt;endl;memset(buf3,0,60);memcpy(buf3,&amp;s3,sizeof(s3));//将结构体3送入char 数组,进行发送TransmitMessage(2,buf3,sizeof(s3));//发送结构体4cout&lt;&lt;"发送结构体3"&lt;&lt;endl; return 1; } //消息发送函数int Node::TransmitMessage(int ParticipatorID,char *StructBuffer,int BufferLength){ char SendBuffer[1024];memset(SendBuffer,0,1024);//将消息放入特定长度的缓冲区进行发送memcpy(SendBuffer,StructBuffer,BufferLength); SOCKET SendSocket = ::socket(AF_INET,SOCK_DGRAM, 0); SOCKADDR_IN bcast;bcast.sin_family = AF_INET;bcast.sin_port=htons(10000+ParticipatorID);//目标地址的端口号设置bcast.sin_addr.S_un.S_addr=::inet_addr("127.0.0.1");//目标地址设置//发送数据if(sendto(SendSocket, SendBuffer,1024, 0, (sockaddr*)&amp;bcast,sizeof(bcast))==SOCKET_ERROR){ cout&lt;&lt;"数据发送错误"&lt;&lt;endl;return 0; } return 1; } 3.testmian,cpp[plain] view plain copy#include "Node.h" int main() { int ret; WSADATA wsa; //初始化套接字DLLif(WSAStartup(MAKEWORD(2,2),&amp;wsa)!=0){ cout&lt;&lt;"套接字初始化失败!"&lt;&lt;endl; } char MessageBuffer[1024]; Node A; MSG ThreadMessage;A.StartMyThread();//启动新线程ret=A.SendStruct();//发送结构体数据if(ret==1){ system("pause"); return 1; } while(1)//循环接收线程的消息{ if(PeekMessage(&amp;ThreadMessage,NULL ,0,0,PM_REMOVE))//搜集线程的消息{ if(ThreadMessage.message==WM_PARTY_MSG)//判断消息类型{ memcpy(MessageBuffer,(char *)ThreadMessage.lParam,1024);//提取需要处理的网络信息ret=A.DealMessage(MessageBuffer,1024);//处理网络信息if(ret==0)break; } } }system("pause"); }三.运行截图该程序在VC60平台下编译通过顶3踩。

相关文档
最新文档