天天看點

Socket程式設計中如何發送結構體,拼接多次接收消息及擷取通信雙方位址

用戶端:

#include <iostream>
#include <stdio.h>
#include <string>
#include "winsock.h"
#pragma comment(lib, "wsock32")

using namespace std;

#define COMMAND 100

int main()
{
	int ret = 0;

	WSADATA wsadata;
	WORD version = MAKEWORD(2,0);
	ret = WSAStartup(version,&wsadata);

	SOCKET m_hClientSocket;
	m_hClientSocket = socket(AF_INET,SOCK_STREAM,0);

	SOCKADDR_IN m_addr1;
	m_addr1.sin_family = AF_INET;
	m_addr1.sin_addr.S_un.S_addr = inet_addr("192.168.100.57");
	m_addr1.sin_port = htons(10000);
	ret = connect(m_hClientSocket,(LPSOCKADDR)&m_addr1,sizeof(m_addr1));

	char Clisend_msg[] = "我是用戶端,請問你是那位?";
	//char Clisend_msg[] = "hello, I am a client, and who are you?";
	int len_send = send(m_hClientSocket,Clisend_msg,sizeof(Clisend_msg),0);

	//利用字元串發送,規定好字元串格式在伺服器端接收後進行解析
	/*char send_buf[1024] = "tony  2000  ";
	int len_send = send(m_hClientSocket,send_buf,sizeof(send_buf),0);*/

	//使用結構體轉換成字元串發送,在伺服器端直接轉為結構體
	/*
	char send_buf[1024] = "tony  2000  ";
	memset(send_buf,0,1024);
	struct msg
	{
		int cmd;
		int sendID;
		int recvID;
		string name;
		int number;
	};
	msg msg1;
	msg1.cmd = COMMAND;
	msg1.sendID = 2120100324;
	msg1.recvID = 2120100325;
	msg1.name = "Tony";
	msg1.number = 2000;
	

	//以字元串形式發送,因為TCP/IP是位元組流通信
	//memcpy(send_buf,&msg1,sizeof(msg));
	//int len_send = send(m_hClientSocket,send_buf,sizeof(send_buf),0);
	int len_send = send(m_hClientSocket,(char *)&msg1,sizeof(msg),0);
	*/

	closesocket(m_hClientSocket);
	WSACleanup();

	return 0;
}
           

伺服器端代碼:

#include <iostream>
#include <stdio.h>
#include <string>
#include "winsock.h"
#pragma comment(lib, "wsock32")

using namespace std;

int main()
{
	//建立socket程式設計環境
	int ret = 0;
	WSADATA wsadata;
	WORD version = MAKEWORD(2,0);
	ret = WSAStartup(version,&wsadata);

	//伺服器端口建立
	SOCKET m_hServerSocket;
	m_hServerSocket = socket(AF_INET,SOCK_STREAM,0);
	if(INVALID_SOCKET == m_hServerSocket)
	{
		cout << "伺服器socket建立失敗!" << endl;
		return 0;
	}
	else
	{
		cout << "伺服器socket建立成功" << endl;
	}
	cout << endl;

	//伺服器端口綁定
	SOCKADDR_IN m_addr;
	m_addr.sin_family = AF_INET;
	m_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	m_addr.sin_port = htons(10000);
	ret = bind(m_hServerSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));
	

	//伺服器端口開始監聽
	ret = listen(m_hServerSocket,20);//第二個參數指定最大申請的連接配接數

	//每當有一個用戶端連接配接申請,則伺服器端建立一個線程對其進行處理,模拟資料庫伺服器的處理方式
	SOCKET com_Sock;
	SOCKADDR_IN clntaddr;
	int clnlen = sizeof(clntaddr);
	struct msg
	{
		int cmd;
		int sendID;
		int recvID;
		string name;
		int number;
	};
	msg msg2;
	
	while(1)
	{
		int count = 0;
		//com_Sock = accept(m_hServerSocket,NULL,NULL);
		com_Sock = accept(m_hServerSocket,(SOCKADDR *)&clntaddr,&clnlen);
		/*cout << inet_ntoa(clntaddr.sin_addr) << endl;

		getpeername(com_Sock,(SOCKADDR *)&clntaddr,&clnlen);
		cout << inet_ntoa(clntaddr.sin_addr) << endl;*/
		getsockname(com_Sock,(SOCKADDR *)&clntaddr,&clnlen);
		cout << inet_ntoa(clntaddr.sin_addr) << endl;

		char recv_msg[16];
		memset(recv_msg,0,16);
		ret = recv(com_Sock,recv_msg,sizeof(recv_msg),0);
		cout << ret << endl;

		//根據給定的字元串格式進行解析
		/*
		for (int i=0;i<4;i++)
		{
			cout << recv_msg[i];
		}
		cout << endl;
		for (int j=6; j<10; j++)
		{
			cout << recv_msg[j];
		}
		cout << endl;*/

		//直接将接收到的位元組流拷貝給相應的結構體即可。
		/*
		memset(&msg2,0,sizeof(msg));
		memcpy(&msg2,recv_msg,sizeof(msg));
		cout << msg2.cmd << endl;
		cout << msg2.sendID << endl;
		cout << msg2.recvID << endl;
		cout << msg2.name << endl;
		cout << msg2.number << endl;
		*/


		//在伺服器端把多次接收的資訊拼接到一起
		char receive[1000];
		memset(receive,0,sizeof(receive));
		int k = 0;

		while (ret > 0)
		{
			for (int m=0; m<16; m++)
			{
				receive[k] = recv_msg[m];
				k++;
			}

			cout << ret << endl;
			count += ret;
			//這裡必須加上字元串結束辨別,否則會亂碼,雖然這已經不是這個
			//數組的單元了。由字元串性質決定的。雖然接受字元串末尾的結束辨別,但是如果分多次接收的時候就不行了			                        recv_msg[ret] = '\0';      
			cout << recv_msg << endl;
			ret = recv(com_Sock,recv_msg,sizeof(recv_msg),0);
		}
		cout << count << endl;
		
		cout << receive << endl;
		cout << strlen(receive) << endl;

		closesocket(com_Sock);
	}

	WSACleanup();

	return 0;
}