基于连接的Tcp编程.
代码注释,如下:
- #include <stdio.h>
- #include <winsock2.h>
- #pragma comment(lib,"WS2_32.lib")
- #define BUF_SIZE 64
- int main()
- {
- WSADATA wsadata; //包含DLL期望程序使用的版本和支持的最高版本等字段
- int retVal;
- SOCKET sServer;
- SOCKET sClient;
- char buf[BUF_SIZE];
- //
- retVal=WSAStartup(MAKEWORD(2,2),&wsadata);
- if(retVal != 0)
- {
- printf("WSAStartup failed!\n");
- }
- //创建套接字
- sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
- if(sServer == INVALID_SOCKET)
- {
- printf("socket failed!\n");
- WSACleanup();
- return -1;
- }
- //绑定套接字
- SOCKADDR_IN addrServ;
- addrServ.sin_family=AF_INET; //套接字属于协议族TCP/IP
- addrServ.sin_port=htons(4999);
- addrServ.sin_addr.S_un.S_addr=INADDR_ANY;
- retVal=bind(sServer,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));
- if(retVal == SOCKET_ERROR)
- {
- printf("bind failed!\n");
- closesocket(sServer);
- WSACleanup();
- return -1;
- }
- //
- retVal=listen(sServer,1);
- if(retVal == SOCKET_ERROR)
- {
- printf("listen failed!\n");
- closesocket(sServer);
- WSACleanup();
- return -1;
- }
- //等待客户端的连接请求
- SOCKADDR_IN addrClient;
- int len=sizeof(SOCKADDR_IN);
- sClient=accept(sServer,(LPSOCKADDR)&addrClient,&len); //返回一个新的套接字句柄
- if(sClient == INVALID_SOCKET)
- {
- printf("accept failed!\n");
- closesocket(sServer);
- WSACleanup();
- return -1;
- }
- //接收数据
- ZeroMemory(buf,BUF_SIZE);
- retVal=recv(sClient,buf,BUF_SIZE,0);
- if(retVal == SOCKET_ERROR)
- {
- printf("recv failed!\n");
- closesocket(sClient);
- closesocket(sServer);
- WSACleanup();
- return -1;
- }
- //
- printf("Server receives data: ");
- printf("%s\n",buf);
- //
- closesocket(sClient);
- closesocket(sServer);
- WSACleanup();
- return 0;
- }
- //Client.cpp
- #include <stdio.h>
- #include <winsock2.h>
- #pragma comment(lib,"WS2_32.lib")
- #define BUF_SIZE 64
- int main()
- {
- WSADATA wsadata;
- int retVal;
- SOCKET sClient;
- char buf[BUF_SIZE];
- //加载套接字DLL
- retVal=WSAStartup(MAKEWORD(2,2),&wsadata);
- if(retVal != 0)
- {
- printf("WSAStartup failed!\n");
- }
- //创建套接字
- sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
- if(sClient == INVALID_SOCKET)
- {
- printf("socket failed!\n");
- WSACleanup();
- return -1;
- }
- //
- SOCKADDR_IN addrServ;
- addrServ.sin_family=AF_INET; //套接字属于协议族TCP/IP
- addrServ.sin_port=htons(4999);
- addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
- retVal=connect(sClient,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));
- if(retVal == SOCKET_ERROR)
- {
- printf("connect failed!\n");
- closesocket(sClient);
- WSACleanup();
- return -1;
- }
- //发送数据
- ZeroMemory(buf,BUF_SIZE);
- strcpy(buf,"Hello Tcp!");
- retVal=send(sClient,buf,BUF_SIZE,0);
- if(retVal == SOCKET_ERROR)
- {
- printf("send failed!\n");
- closesocket(sClient);
- WSACleanup();
- return -1;
- }
- //
- closesocket(sClient);
- WSACleanup();
- return 0;
- }
函数原型:
1.
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr_in *PSOCKADDR_IN;
typedef struct sockaddr_in FAR *LPSOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
typedef struct sockaddr *PSOCKADDR;
typedef struct sockaddr FAR *LPSOCKADDR;
struct sockaddr_in{ short sin_family; unsigned short sin_port; IN_ADDR sin_addr; char sin_zero[8]; };
short sin_family; //AF_INET,代表TCP/IP协议族
char sin_zero[8]; //填充大小和SOCKADDR结构一样(16Byetes)
typedef struct in_addr {
union {
struct {
u_char s_b1,s_b2,s_b3,s_b4;
} S_un_b;
struct {
u_short s_w1,s_w2;
} S_un_w;
u_long S_addr;
} S_un; } in_addr;
struct sockaddr { u_short sa_family; char sa_data[14]; };
注:1.SOCKADDR更通用,SOCKADDR_IN针对TCP/IP协议族;2.SOCKADDR_IN弥补了SOCKADDR的地址和端口没有分开的缺陷;3.SOCKADDR_IN用于定义,SOCKADDR用于函数的参数.
2.
SOCKET accept( SOCKET s, struct sockaddr* addr, int* addrlen );int connect( SOCKET s, const struct sockaddr FAR* name, int namelen );Return Values
If no error occurs, accept returns a value of type SOCKET that is a descriptor for the new socket. This returned value is a handle for the socket on which the actual connection is made.
Otherwise, a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by calling WSAGetLastError.
int recv( SOCKET s, char* buf, int len, int flags );int send( SOCKET s, const char FAR* buf, int len, int flags );
int flags //The flag that specifies the way in which the call is made. (0 | MSG_OOB | MSG_PEEK)
unsigned long inet_addr( const char* cp );int WSACleanup (void);
int bind( SOCKET s, const struct sockaddr FAR* name, int namelen );
int listen( SOCKET s, int backlog ); int backlog //Maximum length of the queue of pending connections
*******************************************************************
typedef u_int SOCKET;
SOCKET socket( int af, int type, int protocol );
int type, //SOCK_STREAM | SOCK_DGRAM
int protocol //IPPROTO_TCP | IPPROTO_UDP
注:所谓的套接字类型(SOCKET)、协议类型(type)、句柄(HANDLE),以及套接字种类(Type)其本身都只是int 整型或者u_int,是一个32位的数字. 你给函数参数指定一个数值,系统就自动调用对应的各种类型数据(然而,实际上,内部全部是封装的,它的实现机制你一窍不通!)