TCP/IP網路程式設計學習之路二
基於Windows下的網路程式設計:
網路程式設計基本上都有伺服器端和客戶端,這兩個端所實現的方法是不一樣的。
伺服器端的一般框架
- 用socket()函式建立一個套接字,並建立資源所使用的資源 SOCKET socket(int af,int type,int protocol)
- 用bind()函式繫結套接字,併為其分配IP 地址和埠號 int PASCAL FAR bind( SOCKET s,const struct sockaddr FAR *name,int namelen )
- 用listen()函式監聽是否有客戶端想連線 int PASCAL FAR listen( SOCKET s, int backlog )
- 用accept()函式來接收客戶端的連線請求, 同時建立一個新的套接字來和客戶端通訊 SOCKET PASCAL FAR accept(SCOKET s,struct sockaddr FAR *addr,int FAR *addrlen);
- 用socket()函式建立一個套接字,並建立資源所使用的資源 SOCKET socket(int af,int type,int protocol)
- 用connect()函式來連線伺服器int PASCAL FAR connect( SOCKET s,const struct sockaddr FAR *name,int namelen );
接下來解釋函式引數的意思
SOCKET PASCAL FAR socket( int af,int type,int protocol );
af 表示套接字中使用的協議族資訊, type表示套接字的型別(面向連線的或者面向無連線的),protocol表示計算機間通訊中使用的協議資訊(一般寫0);
int PASCAL FAR bind( SOCKET s,const struct sockaddr FAR *name,int namelen );
s 是socket()函式建立的套接字 name 是Socket的位址值,其格式為 struct sockaddr { u_short sa_family; char sa_data[14]; }; namelen 是name的長度
int PASCAL FAR listen( SOCKET s, int backlog );
s是socket()函式建立的套接字, backlog是最多允許的連線數。
SOCKET PASCAL FAR accept(SCOKET s,struct sockaddr FAR *addr,int FAR *addrlen);
s 是socket()函式建立的套接字, addr 存放來連線的彼端的位址; addrlen addr的長度,這個函式會返回新的套接字!
int PASCAL FAR connect( SOCKET s,const struct sockaddr FAR *name,int namelen );
s是客戶端通過socket()函式建立的套接字,name 是此 Socket 想要連線的對方位址 namelen 是name的長度;
伺服器的基本框架
#include <iostream>
#include <WinSock2.h>
#include <cstdlib>
#include <cstring>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
const int MAXLENGTH = 4096;
int main()
{
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(result != NO_ERROR)
{
cerr << "init winsock failured" << endl;
exit(1);
}
SOCKET serversocket;
serversocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(serversocket == INVALID_SOCKET)
{
cout << "建立socket失敗" << WSAGetLastError() << endl;
system("pause");
return -1;
}
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(6800);
result = bind(serversocket, (struct sockaddr *)&server, sizeof(server));
if(result == SOCKET_ERROR)
{
cout << "繫結失敗" << endl;
system("pause");
return -1;
}
result = listen(serversocket, 5);
if(result == SOCKET_ERROR)
{
cout << "監聽失敗" << endl;
system("pause");
return -1;
}
char recvbuf[1024];
struct sockaddr_in client;
int length =sizeof(client);
SOCKET acceptsock = accept(serversocket, (struct sockaddr *)&client, &length);
if(acceptsock == INVALID_SOCKET)
{
cout << "接受失敗" << endl;
system("pause");
return -1;
}
result = recv(acceptsock, recvbuf, strlen(recvbuf), 0);
if(result == SOCKET_ERROR)
{
cout << "接收失敗" << endl;
system("pause");
return -1;
}
cout << recvbuf << endl;
cin >> recvbuf;
result = send(acceptsock, recvbuf, strlen(recvbuf), 0);
if(result == SOCKET_ERROR)
{
cout << "傳送失敗" << endl;
system("pause");
return -1;
}
closesocket(acceptsock);
closesocket(serversocket);
WSACleanup();
system("pause");
return 0;
}
客戶端的基本框架
#include <iostream>
#include <WinSock2.h>
#include <cstring>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if(ret != 0)
{
cout << "初始化win失敗" << endl;
system("pause");
return -1;
}
SOCKET clientsocket;
clientsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(clientsocket == SOCKET_ERROR)
{
cout << "建立socket失敗" << endl;
system("pause");
return -1;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(6800);
ret = connect(clientsocket, (struct sockaddr *)&server, sizeof(server));
if(ret == SOCKET_ERROR)
{
cout << "連線失敗" << GetLastError() << endl;
system("pause");
return -1;
}
char buffer[1024];
cin >> buffer;
ret = send(clientsocket, buffer, strlen(buffer), 0);
if(ret == SOCKET_ERROR)
{
cout << "傳送失敗" << GetLastError() << endl;
system("pause");
return -1;
}
ret = recv(clientsocket, buffer, strlen(buffer), 0);
if(ret == SOCKET_ERROR)
{
cout << "接收失敗" << GetLastError() << endl;
system("pause");
return -1;
}
cout << buffer << endl;
closesocket(clientsocket);
WSACleanup();
system("pause");
return 0;
}