`
westice
  • 浏览: 114240 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

C++版socket

阅读更多

以前纠结过java版的socket通信,现在搞c++的。都是基于tcp/ip的,形式差不多,需要注意的只是细节问题。

服务器socket绑定一个端口,然后等待客户机的接入。

客户端socket去连服务器和一个特定端口,连接成功后即可进行通信,发送字符串。

客户端代码:

#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
/*
*客户端
*/
int main()
{   
	cout<<"客户端启动"<<endl;
	//初始化winsock
	WSADATA wsaD;
    WSAStartup(MAKEWORD(1,1),&wsaD);
	//创建客户端socket
	SOCKET sclient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	//连接服务器
	struct sockaddr_in servaddr;
	servaddr.sin_family=AF_INET;
	servaddr.sin_addr.s_addr=inet_addr("192.168.1.45"); //指定服务器
	servaddr.sin_port=htons(8080);             //指定端口
    cout<<"确实要建立连接? yes/no"<<endl;
	char flag[3];
	gets(flag);
	if(strcmp(flag,"yes")==0)
	{
      connect(sclient,(struct sockaddr*)&servaddr,sizeof(servaddr)); //通过套接字连接主机
    }                               
	//发送数据
	char buf[500];
    cout<<"输入发送内容:";
	while(cin.getline(buf,500))
	{
     //通过套接字给主机发送字符串
	 send(sclient,buf,strlen(buf)+1,0);  //字符串还有个结束标志,  
	}
	return 0;
}
 

服务器代码:

#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using std::cout;
using std::cin;
using std::string;
using std::endl;
/*
*socket 服务器端 
*/ 
int main()
{
    cout<<"服务器启动!....."<<endl;
    //初始化winsock 
     WSADATA wsaD;
     WSAStartup(MAKEWORD(1,1),&wsaD);
    //创建监听套接字
    SOCKET slisten=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
    // 绑定主机地址和监听套接字
    struct sockaddr_in my_addr;   //主机地址 
    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(8080); //指定端口
    my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    bind(slisten,(struct sockaddr *)&my_addr,sizeof(my_addr));
    //启动监听
    listen(slisten,5);
    //开始接收数据
    struct sockaddr_in c_addr;  //客户地址 
    int addr_len=sizeof(c_addr);
    SOCKET sconnect=accept(slisten,(struct sockaddr*)&c_addr,&addr_len); //通过监听套接字创建连接套接字
    cout<<"连接已建立......"<<endl;
    while(true)
    {  
	   char buf[500]; //存储接收的字符
       int len=recv(sconnect,buf,sizeof(buf),0);  //通过连接套接字接收数据
       if(len>0)
       {
          cout<<"客户说:"<<buf<<endl;
       }
    } 
	return 0;
}
 

 

 在创建socket之前要调用WSAStartup(MAKEWORD(1,1),&wsad);

 这个函数说明使用的版本是1.1版的,wsad存储系统返回的winsocket信息。

 

创建socket 调用socket(int af,int type,int protocol) af不清楚,type有SOCK_STREAM(tcp),SOCK_DGRAM(udp)

protocol :通信协议(默认为0)

 

绑定端口,调用函数bind(SOCKET S,stuct sockaddr *name,int namelen),

S为监听socket,name为主机地址(里面指定了端口) ,namelen为地址变量长度。

 

接下来使服务器处于监听状态,调用函数listen(SOCKET s,int backlog)

s为监听socket, backlog为最大连接数,最大为5.

 

客户机连进来后就可通信了,但还要创建一个连接socket.调用accept(SOCKET S,struct sockaddr *addr int *addrlen);

s为监听socket,addr用来存放客户地址,addrlen为长度,然后返回连接socket.

这一步后就可以利用连接socket接收数据了,调用recv(SOCKET s,char *buf,int len,int flags).

s为连接socket,buf来存放接收数据,他为一个字符数组首地址。len为buf的最大长度,不是buf的实际长度,flags为此函数调用的方式(不太清楚)

 

而客户端跟java里的一样要简单一点,首先调用WSAStartup(),然后再 socket()创建客户端socket。指定主机的ip和开放的端口,就可以尝试和主机联机了,调用connect(SOCKET s,struct sockaddr addr,int len)

s为客户端socket,addr为主机地址,len为地址变量长度,这一步成功后,就可以给主机发送消息了,

调用send(SOCKET S,char *buf,int len,int flags),

s为客户端socket ,buf为字符串,len为字符串长度(里面一定要包含结束标志的长度) ,flags此函数调用的方式。

 

数据发送完毕后就要关闭连接,服务器端和客户端都可以关闭,调用函数closesocket(SOCKET S),S为要关闭的socket,

然后再调用WSACleanup()释放socket所占用的资源。

 

/*
*封装之后的接受函数 
*因为要判断每次接收了多少字节 
*/
bool my_recv(SOCKET socket,char *buf,int length,int flag){
     int recv_len = 0;
     short index = 0;
     while( length > 0 ){
       recv_len = recv(socket,&buf[index],length,flag);
       index = index + recv_len;
       length = length - recv_len;
     }
     
     if( 0 == recv_len ){
        return true;    
     }else{
        return false;
     }
}
 

 

 

在探讨这个问题时纠结过的问题:

//要包含这两句
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

 

 

然后这个程序是window 控制台程序,在vc里的Project Options中将/subsystem:windows改成/subsystem:console
本来想在dev-cpp里玩的,调了老半天没搞好,最后还是在vc里玩的,我一直喜欢开源的东西

 

分享到:
评论
1 楼 nima123321 2013-11-29  
网上的人,发发代码就算了,但是最起码标明一个该代码是否能用嘛.

相关推荐

Global site tag (gtag.js) - Google Analytics