1. 程式人生 > >TCP/IP網路程式設計學習之路二

TCP/IP網路程式設計學習之路二

基於Windows下的網路程式設計:

網路程式設計基本上都有伺服器端和客戶端,這兩個端所實現的方法是不一樣的。

伺服器端的一般框架

  1. 用socket()函式建立一個套接字,並建立資源所使用的資源 SOCKET socket(int af,int type,int protocol) 
  2. 用bind()函式繫結套接字,併為其分配IP 地址和埠號 int PASCAL FAR bind( SOCKET s,const struct sockaddr FAR *name,int namelen )
  3. 用listen()函式監聽是否有客戶端想連線 int PASCAL FAR listen( SOCKET s, int backlog )
  4. 用accept()函式來接收客戶端的連線請求, 同時建立一個新的套接字來和客戶端通訊    SOCKET PASCAL FAR accept(SCOKET s,struct sockaddr FAR *addr,int FAR *addrlen);
客戶端的一般框架
  1. 用socket()函式建立一個套接字,並建立資源所使用的資源 SOCKET socket(int af,int type,int protocol) 
  2. 用connect()函式來連線伺服器int PASCAL FAR connect( SOCKET s,const struct sockaddr FAR *name,int namelen );
只有我們寫完這些步驟,伺服器和客戶端才有可能聯通,【注意】伺服器通過accept()生成的套接字和客戶端生成的套接字來通訊!

接下來解釋函式引數的意思

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;
}