1. 程式人生 > >一個socket程式設計的簡單示例

一個socket程式設計的簡單示例

        1.什麼是socket(參考:百度百科)

           所謂socket通常也稱作"套接字",應用程式通常通過"套接字"向網路發出請求或者應答網路請求。以J2SDK-1.3為例,Socket和ServerSocket類庫位於java .net包中。ServerSocket用於伺服器端,Socket是建立網路連線時使用的。在連線成功時,應用程式兩端都會產生一個Socket例項,操作這個例項,完成所需的會話。對於一個網路連線來說,套接字是平等的,並沒有差別,不因為在伺服器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。

        2.socket連線過程(參考:百度百科)

        根據連線啟動的方式以及本地套接字要連線的目標,套接字之間的連線過程可以分為三個步驟:伺服器監聽,客戶端請求,連線確認。         a.伺服器監聽:是伺服器端套接字並不定位具體的客戶端套接字,而是處於等待連線的狀態,實時監控網路狀態。
        b.客戶端請求:是指由客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描述它要連線的伺服器的套接字,指出伺服器端套接字的地址和埠號,然後就向伺服器端套接字提出連線請求。
        c.連線確認:是指當伺服器端套接字監聽到或者說接收到客戶端套接字的連線請求,它就響應客戶端套接字的請求,建立一個新的執行緒,把伺服器端套接字的描述發給客戶端,一旦客戶端確認了此描述,連線就建立好了。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連線請求.

        socket連線流程圖(以tcp/ip為例):(來源:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx)

        

           3.簡單的示例程式碼

            a.server端

	//socket初始化
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		return 0;
	}

	//建立socket
	int nServerId = socket(AF_INET,SOCK_STREAM,0);
	if(nServerId == -1)
	{
		return 0;
	}

	//呼叫bind函式將其與本機地址以及一個本地埠號繫結
	sockaddr_in inet_addr;
	inet_addr.sin_family = AF_INET;        //協議型別是INET
	inet_addr.sin_addr.s_addr = INADDR_ANY;//本機IP
	inet_addr.sin_port = htons(8080);      //指定埠號
	if (bind(nServerId, (sockaddr *) & inet_addr, sizeof(inet_addr)) < 0)
	{
		int nErr = WSAGetLastError();
		//關閉socket
		closesocket(nServerId);
		return 0;
	}

	//開始監聽,最多允許128個客戶端同時連結
	if (listen(nServerId, 128) < 0)
	{
		//關閉socket
		closesocket(nServerId);
		return 0;
	}

	while(1)
	{
		sockaddr_in	inet_addr;
		int len = sizeof(inet_addr);
		// accept 會阻塞程序,直到有客戶端連線上來為止
		SOCKET clientSocket = accept(nServerId, (sockaddr *)&inet_addr, &len);
		if (clientSocket == INVALID_SOCKET)
		{
			return 0;
		}
		printf("received a connection from %s %d", inet_ntoa(inet_addr.sin_addr),clientSocket); 
		//發訊息給客戶端
		send(clientSocket,"you are collected!",4096,0);

		//接受來自客戶端的訊息
		const int nBufSize = 4096;
		char	buf[nBufSize];
		int nReciveSize = recv(clientSocket, buf, nBufSize, 0);
		if (nReciveSize > 0)
		{
			printf("%s ", buf);
		}
		// 關閉socket
        closesocket(clientSocket);
	}


            b.client端

//socket初始化
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		return 0;
	}

	//建立socket
	int nClientId = socket(AF_INET,SOCK_STREAM,0);
	if(nClientId == -1)
	{
		return 0;
	}

	//獲取伺服器地址
	hostent	*host = gethostbyname("wz");
	if(host==NULL)
	{
		return 0;
	}

	sockaddr_in	inet_addr;
	memset(&inet_addr, 0, sizeof(inet_addr));
	inet_addr.sin_family = AF_INET;	
	memcpy(&inet_addr.sin_addr, host->h_addr, sizeof(inet_addr.sin_addr));
	inet_addr.sin_port = htons(8080); //指定埠
	//同服務端連線
	if(connect(nClientId,(sockaddr*)&inet_addr,sizeof(sockaddr_in))<0)
	{
		closesocket(nClientId);
		return 0;
	}

	const int nBufSize = 4096;
	char	buf[nBufSize];
	//接受從服務端來的訊息
	int nReciveSize = recv(nClientId, buf, nBufSize, 0);
	if (nReciveSize <= 0)
	{
		closesocket(nClientId);
		return 0;
	}
	printf("%s,%d ", buf,nClientId);
	//發訊息給服務端
	if(send(nClientId,"thanks!",4096,0)<0)
	{
		return 0;
	}