uintptr_t _beginthread( void( *start_address )( void * ), unsigned stack_size, void *arglist );第一个参数是一个函数指针,这个 自己定义的函数返回类型是void,参数是void*;
第三个参数是要传递的参数。
如图:不同的线程使用的栈是不一样的,所以两个进程中的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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
socket 网络编程快速入门(二)教你编写基于UDP/TCP的服务端多线程通信
原文地址:http://blog.csdn.net/nk_test/article/details/47756381