Tcp

基於連接的Tcp編程.

 

代碼註釋,如下:

  1. #include <stdio.h>  
  2. #include <winsock2.h>  
  3. #pragma comment(lib,"WS2_32.lib")  
  4.  
  5. #define BUF_SIZE 64  
  6.  
  7. int main()  
  8. {  
  9.     WSADATA wsadata; //包含DLL期望程序使用的版本和支持的最高版本等字段  
  10.     int retVal;  
  11.  
  12.     SOCKET sServer;  
  13.     SOCKET sClient;  
  14.     char buf[BUF_SIZE];  
  15.  
  16.     //  
  17.     retVal=WSAStartup(MAKEWORD(2,2),&wsadata);  
  18.     if(retVal != 0)  
  19.     {  
  20.         printf("WSAStartup failed!\n");  
  21.     }  
  22.  
  23.     //創建套接字  
  24.     sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);  
  25.     if(sServer == INVALID_SOCKET)  
  26.     {  
  27.         printf("socket failed!\n");  
  28.  
  29.         WSACleanup();  
  30.         return -1;  
  31.     }  
  32.  
  33.     //綁定套接字  
  34.     SOCKADDR_IN addrServ;  
  35.     addrServ.sin_family=AF_INET; //套接字屬於協議族TCP/IP  
  36.     addrServ.sin_port=htons(4999);  
  37.     addrServ.sin_addr.S_un.S_addr=INADDR_ANY;  
  38.  
  39.     retVal=bind(sServer,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));  
  40.     if(retVal == SOCKET_ERROR)  
  41.     {  
  42.         printf("bind failed!\n");  
  43.  
  44.         closesocket(sServer);  
  45.         WSACleanup();  
  46.         return -1;  
  47.     }  
  48.  
  49.     //  
  50.     retVal=listen(sServer,1);  
  51.     if(retVal == SOCKET_ERROR)  
  52.     {  
  53.         printf("listen failed!\n");  
  54.  
  55.         closesocket(sServer);  
  56.         WSACleanup();  
  57.         return -1;  
  58.     }  
  59.  
  60.     //等待客戶端的連接請求  
  61.     SOCKADDR_IN addrClient;  
  62.     int len=sizeof(SOCKADDR_IN);  
  63.  
  64.     sClient=accept(sServer,(LPSOCKADDR)&addrClient,&len); //返回一個新的套接字句柄  
  65.     if(sClient == INVALID_SOCKET)  
  66.     {  
  67.         printf("accept failed!\n");  
  68.  
  69.         closesocket(sServer);  
  70.         WSACleanup();  
  71.         return -1;  
  72.     }  
  73.  
  74.     //接收數據  
  75.     ZeroMemory(buf,BUF_SIZE);  
  76.  
  77.     retVal=recv(sClient,buf,BUF_SIZE,0);  
  78.     if(retVal == SOCKET_ERROR)  
  79.     {  
  80.         printf("recv failed!\n");  
  81.  
  82.         closesocket(sClient);  
  83.         closesocket(sServer);  
  84.         WSACleanup();  
  85.         return -1;  
  86.     }  
  87.  
  88.     //  
  89.     printf("Server receives data: ");  
  90.     printf("%s\n",buf);  
  91.  
  92.     //  
  93.     closesocket(sClient);  
  94.     closesocket(sServer);  
  95.     WSACleanup();  
  96.     return 0;  
  97. }  

 

  1. //Client.cpp  
  2. #include <stdio.h>  
  3. #include <winsock2.h>  
  4. #pragma comment(lib,"WS2_32.lib")  
  5.  
  6. #define BUF_SIZE 64  
  7.  
  8. int main()  
  9. {  
  10.     WSADATA wsadata;  
  11.     int retVal;  
  12.  
  13.     SOCKET sClient;  
  14.     char buf[BUF_SIZE];  
  15.  
  16.  
  17.     //加載套接字DLL  
  18.     retVal=WSAStartup(MAKEWORD(2,2),&wsadata);  
  19.     if(retVal != 0)  
  20.     {  
  21.         printf("WSAStartup failed!\n");  
  22.     }  
  23.  
  24.     //創建套接字  
  25.     sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);  
  26.     if(sClient == INVALID_SOCKET)  
  27.     {  
  28.         printf("socket failed!\n");  
  29.  
  30.         WSACleanup();  
  31.         return -1;  
  32.     }  
  33.  
  34.     //  
  35.     SOCKADDR_IN addrServ;  
  36.     addrServ.sin_family=AF_INET; //套接字屬於協議族TCP/IP  
  37.     addrServ.sin_port=htons(4999);  
  38.     addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");  
  39.  
  40.     retVal=connect(sClient,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));  
  41.     if(retVal == SOCKET_ERROR)  
  42.     {  
  43.         printf("connect failed!\n");  
  44.  
  45.         closesocket(sClient);  
  46.         WSACleanup();  
  47.         return -1;  
  48.     }  
  49.  
  50.     //發送數據  
  51.     ZeroMemory(buf,BUF_SIZE);  
  52.     strcpy(buf,"Hello Tcp!");  
  53.  
  54.     retVal=send(sClient,buf,BUF_SIZE,0);  
  55.     if(retVal == SOCKET_ERROR)  
  56.     {  
  57.         printf("send failed!\n");  
  58.  
  59.         closesocket(sClient);  
  60.         WSACleanup();  
  61.         return -1;  
  62.     }  
  63.  
  64.     //  
  65.     closesocket(sClient);  
  66.     WSACleanup();  
  67.     return 0;  
  68. }  

函數原型:

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位的數字. 你給函數參數指定一個數值,系統就自動調用對應的各種類型數據(然而,實際上,內部全部是封裝的,它的實現機制你一竅不通!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章