最简单的Tcp连接的例子
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最简单的Tcp连接的例子相关的知识,希望对你有一定的参考价值。
1.服务器代码
#include <Windows.h> //ws2_32.lib对应ws2_32.dll,提供了对网络相关API的支持 #pragma comment(lib, "ws2_32.lib") int _tmain(int argc, _TCHAR* argv[]) { /* 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; */ WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { /* WORD MAKEWORD ( BYTE bLow, //指定新变量的低字节序; BYTE bHigh //指定新变量的高字节序; ); //typedef unsigned short WORD; WORD temValue = MAKEWORD(0x12, 0x34); //temValue = 0x3412 */ /* WSAStartup:返回0为成功 WSAStartup应该与WSACleanup成对使用 WSAStartup的功能是初始化Winsock DLL 本函数必须是应用程序或DLL调用的第一个Windows Sockets函数. 它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节. 应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数. */ /* wsaData.wVersion = 0x0202 wsaData.wHighVersion = 0x0202 wsaData.szDescription = 0x0046f2c4 "WinSock 2.0" wsaData.szSystemStatus = 0x0046f3c5 "Running" */ return -1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { /* unsigned short value0 = 0x1234; unsigned short temvalue0 = LOBYTE(value0);//temvalue0 = 0x0034 unsigned short temvalue1 = HIBYTE(value0);//temvalue1 = 0x0012 LOWORD()得到一个32bit数的低16bit HIWORD()得到一个32bit数的高16bit LOBYTE()得到一个16bit数最低(最右边)那个字节 HIBYTE()得到一个16bit数最高(最左边)那个字节 */ WSACleanup(); /* WSACleanup是来解除与Socket库的绑定并且释放Socket库所占用的系统资源。 WSACleanup操作成功返回值为0;否则返回值为SOCKET_ERROR 在一个多线程的环境下,WSACleanup中止了Windows Sockets在所有线程上的操作. */ return -1; } //typedef UINT_PTR SOCKET; //typedef _W64 unsigned int UINT_PTR, *PUINT_PTR; SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0); /* socket():第一个参数指明协议族,主要为AF_INET,AF_INET6,AF_LOCAL等 第二个参数指明套接口类型,主要为SOCK_STREAM,SOCK_DGRAM,SOCK_RAW等 第三个参数一般为0 对于windows环境下,在调用该函数之前需首先调用WSAStartup函数完成对Winsock服务的初始化 成功时,返回一个小的非负整数值,与文件描述符类似。 失败时,返回INVALID_SOCKET */ //AF_INET(又称 PF_INET)是 IPv4 网络协议的套接字类型,AF_INET6 则是 IPv6 的;而 AF_UNIX 则是 Unix 系统本地通信 //#define INVALID_SOCKET (SOCKET)(~0) if (INVALID_SOCKET == sockfd) { WSACleanup(); return 0; } //typedef struct sockaddr_in SOCKADDR_IN; /* struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; typedef struct in_addr { union { struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { USHORT s_w1,s_w2; } S_un_w; ULONG S_addr; } S_un; #define s_addr S_un.S_addr // can be used for most tcp & ip code #define s_host S_un.S_un_b.s_b2 // host on imp #define s_net S_un.S_un_b.s_b1 // network #define s_imp S_un.S_un_w.s_w2 // imp #define s_impno S_un.S_un_b.s_b4 // imp # #define s_lh S_un.S_un_b.s_b3 // logical host } IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR; */ SOCKADDR_IN serAddr = {0}; //#define AF_INET 2 // internetwork: UDP, TCP, etc. serAddr.sin_family = AF_INET; //u_short PASCAL FAR htons (__in u_short hostshort); //htons 将主机的无符号短整形数转换成网络字节顺序 //字节序是大端在前还是小端在前是取决于cpu的而不是取决于操作系统的,本机为小端模式 //网络字节序:就是大端字节序。规定不同系统间通信一律采用网络字节序。 //unsigned short nvalue = htons(9000); //nvalue = 10275 9000为0x2328 10275为0x2823 serAddr.sin_port = htons(9000); /* htonl()--"Host to Network Long" ntohl()--"Network to Host Long" htons()--"Host to Network Short" ntohs()--"Network to Host Short" */ //inet_addr()的功能是将一个点分十进制的IP转换成一个长整数型数(u_long类型) //serAddr.sin_addr.S_un.S_addr = 0x0100007f 即1 0 0 127 serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); /* struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。 二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。 typedef struct sockaddr { #if (_WIN32_WINNT < 0x0600) u_short sa_family; #else ADDRESS_FAMILY sa_family; // Address family. #endif //(_WIN32_WINNT < 0x0600) CHAR sa_data[14]; // Up to 14 bytes of direct address. } SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR; */ if (SOCKET_ERROR == bind(sockfd, (SOCKADDR*)(&serAddr), sizeof(SOCKADDR))) { /* bind:把一个本地协议地址赋予一个套接字 第一个参数是一个套接字 第二个参数是指向特定于协议的地址结构的指针 第三个参数是该地址结构的长度 */ closesocket(sockfd); WSACleanup(); return -1; } if (listen(sockfd, 10) != 0) { /* 用listen()创建套接口并为申请进入的连接建立一个后备日志,然后便可用accept()接受连接了。 listen()仅适用于支持连接的套接口,如SOCK_STREAM类型的。套接口处于一种“变动”模式, 申请进入的连接请求被确认,并排队等待被接受。这个函数特别适用于同时有多个连接请求的服务器; 如果当一个连接请求到来时,队列已满,那么客户将收到一个WSAECONNREFUSED错误。 如无错误发生,listen()返回0。否则的话,返回-1 */ closesocket(sockfd); WSACleanup(); return -1; } SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); SOCKET clientSocket = accept(sockfd, (SOCKADDR*)&addrClient, &len); if (INVALID_SOCKET == clientSocket) { closesocket(sockfd); WSACleanup(); return -1; } if (send(clientSocket, "1234", 4, 0) <= 0) { closesocket(sockfd); closesocket(clientSocket); WSACleanup(); return -1; } char buff[1024] = {0}; if (recv(clientSocket, buff, 4, 0) <= 0) { closesocket(sockfd); closesocket(clientSocket); WSACleanup(); return -1; } printf("%s\n", buff); system("pause"); //释放套接口描述字, 如无错误发生,则closesocket()返回0。否则的话,返回SOCKET_ERROR错误 closesocket(sockfd); closesocket(clientSocket); //注意点:所有打开的SOCKET都需要进行关闭 WSACleanup(); return 0; }
2.客户端代码
#include <windows.h> #pragma comment(lib, "ws2_32.lib") int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { return -1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { WSACleanup(); return -1; } SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == sockClient) { WSACleanup(); return -1; } SOCKADDR_IN sockAddr = {0}; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(9000); sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //connect 成功则返回0,失败返回-1,错误原因存于errno中。 if (SOCKET_ERROR == connect(sockClient, (SOCKADDR*)&sockAddr, sizeof SOCKADDR)) { //connect在进行连接的时候会默认等待一会,如没有建立连接则返回失败 closesocket(sockClient); WSACleanup(); return -1; } char buff[1024] = {0}; if (recv(sockClient, buff, 4, 0) <= 0) { closesocket(sockClient); WSACleanup(); return -1; } printf("%s\n", buff); if (send(sockClient, "1234", 4, 0) <= 0) { closesocket(sockClient); WSACleanup(); return -1; } system("pause"); closesocket(sockClient); WSACleanup(); return 0; }
以上是关于最简单的Tcp连接的例子的主要内容,如果未能解决你的问题,请参考以下文章