您的位置:首页 > 理论基础 > 计算机网络

socket编程解决网络数据的传输

2014-08-29 10:11 495 查看
socket编程我用的就是原生态的socket,今天也只是学了下原理,写了一个简单的小例子,听说websocket这个第三方库不错,这几天也想学学,看看怎么样吧。原生态的socket我第一次弄,中间出了不少的问题,我把他们都记录了下来,方便以后看吧。明天想移植到android上看看,解决一下编码的问题库的问题什么的,今天把他们的使用方法贴出来,大家可以参考一下。

查看源代码

打印帮助

1
#include "HelloWorldScene.h"
2
//需要包含目录E:\cocos2d-x-2.2\cocos2d-x-2.2\cocos2dx\platform\third_party\win32\pthread
3
#include "pthread.h"
4
 
5
//需要加入库ws2_32.lib
6
//在不同的平台下引入不同的头文件
7
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
8
   
#ifndef _WINSOCKAPI_
9
   
#define _WINSOCKAPI_
10
       
#ifndef _WINSOCK2API
11
       
#define _WINSOCK2API
12
           
#include <WinSock2.h>
13
       
#endif
14
   
#endif
15
#else
16
#include <sys/socket.h>
17
#include <netinet/in.h>
18
#include <sys/types.h>
19
#include <arpa/inet.h>
20
 
21
#endif
22
 
23
typedef
unsigned
int
SOCKET;
以上的代码是在头文件中的申明,这里要注意不同的平台需要包含不同的头文件,thread头文件还要附加包含路径,socket要引入库。

查看源代码

打印帮助

1
//服务器端的代码
2
void
HelloWorld::initSocket()
3
{
4
   
//在windows下要初始化socket库,以下代码本人也不知道含义,不过照抄好了
5
   
#if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
6
       
WORD

wVersionRequested;
7
       
WSADATA wsaData;
8
       
int

err;
9
       
wVersionRequested=MAKEWORD(1,1);
10
       
err=WSAStartup(wVersionRequested,&wsaData);
11
       
if
(err!=0){
12
           
return
;
13
       
}
14
       
if
(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1){
15
           
WSACleanup();
16
           
return
;
17
       
}
18
   
#endif
19
 
20
   
//1、定义一个socket
21
   
//AF_INET ipv4协议 第二个参数代表是TCP通信还是UDP通信
22
   
//SCOK_STREAM是TCP通信,SCOK_DGRAM是UPD通信,第三个参数填0
23
   
//返回socket描述符,失败返回-1
24
   
SOCKET sockid = socket(AF_INET,SOCK_STREAM,0);
25
   
if
(sockid == -1)
26
   
{
27
       
CCLog(
"socket error"
);
28
       
this
->errorCode(sockid);
29
       
return
;
30
   
}
31
 
32
   
CCLog(
"%d"
,sockid);
33
 
34
   
//2 定义通信地址结构体
35
   
struct

sockaddr_in sockaddr;
36
   
//使用ipv4协议族
37
   
sockaddr.sin_family = AF_INET;
38
    
//htons将主机字节序转化为网络字节序,网络字节序统一采用大端格式,而有的主机使用的是小端模式
39
   
//所以要进行转换,sin_port代表的是端口号
40
   
sockaddr.sin_port = htons(8888);
41
   
//想要通信的网络地址
42
   
//inet_addr()将一个以.分割的字符串转化为一个网络地址
43
   
sockaddr.sin_addr.s_addr = inet_addr(
"127.0.0.1"
);
44
   
//以下这句话表示的就是本机的IP地址
45
   
//sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
46
 
47
    
//3 将socket和通信地址结构体绑定
48
   
if
(bind(sockid,(
struct

sockaddr *)&sockaddr,
sizeof
(
struct

sockaddr_in)) == -1)
49
   
{
50
       
//如果失败的话,根据不同的平台做不同的处理
51
       
CCLog(
"bind is error!"
);
52
       
this
->errorCode(sockid);
53
       
return
;
54
   
}
55
 
56
   
//4 监听 第二个参数设置请求排队的最大长度
57
   
//也就是说同一时刻有多个客户端程序可以和服务端相连, 使用这个表示可以接受的排队长度.
58
   
if
(listen(sockid,100) == -1)
59
   
{
60
       
CCLog(
"listen"
);
61
       
this
->errorCode(sockid);
62
       
return
;
63
   
}
64
 
65
   
CCLog(
"everying is ok! and accepting"
);
66
 
67
   
//一个死循环,用来不断接收多个客户端的请求
68
   
while
(1)
69
   
{
70
       
struct

sockaddr_in sockaddr_from;
71
       
int
 
len =
sizeof
(sockaddr_from);
72
        
//accept调用时,服务器端的程序会一直阻塞,直到有一个
73
       
//客户程序发出了连接,这里边的参数和bind函数的参数类似,后俩个参数是用来接受信息的
74
       
//这里要特别的注意,我让这个问题搞了俩个小时了,就是应该用client_socket接受accept返回的值
75
       
//这个值是用来和客户端通信的socket!
76
       
SOCKET client_socket;
77
       
if
((client_socket = accept(sockid,(
struct

sockaddr *)&sockaddr_from,&len)) == -1)
78
       
{
79
           
CCLog(
"accept error"
);
80
           
this
->errorCode(sockid);
81
           
return
;
82
       
}
83
       
//打印客户端的信息
84
       
CCLog(
"client %s accepted! port is %d"
,inet_ntoa(sockaddr_from.sin_addr),
85
           
ntohs(sockaddr_from.sin_port));
86
 
87
       
//创建一个线程,用来处理客户端的请求
88
       
pthread_t pthread_id;
89
       
pthread_create(&pthread_id,NULL,HelloWorld::doSomthing,(
void

*)client_socket);
90
       
char

* a[1];
91
       
pthread_join(pthread_id,(
void

**)a);
92
   
}
93
}
94
 
95
//处理客户端请求的操作写在这里
96
void
* HelloWorld::doSomthing(
void
* sock)
97
{
98
   
SOCKET sockid = (SOCKET)sock;
99
   
CCLog(
"%d"
,sockid);
100
   
char

buf[10];
101
   
int

len;
102
   
//最后一个参数一般设置为0
103
   
len =recv(sockid,buf,
sizeof
(buf),0);
104
   
if
(-1 != len)
105
   
{
106
       
//将客户端的数据打印出来
107
       
CCLog(
"%d"
,len);
108
       
CCLog(
"%s"
,buf);
109
   
}
110
   
else
111
   
{
112
       
CCLog(
"recv failed!"
);
113
       
pthread_exit((
void

*)-1);
114
   
}
115
 
116
   
return

0;
117
}
118
 
119
//socket不成功调用的失败代码
120
void
HelloWorld::errorCode(SOCKET sockid)
121
{
122
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
123
       
closesocket(sockid);
124
       
WSACleanup();
125
#else
126
       
close(sockid);
127
#endif
128
       
return
;
129
}
查看源代码

打印帮助

1
//客户端代码
2
void
HelloWorld::menuCloseCallback(CCObject* pSender)
3
{
4
   
//在windows下要初始化socket库,以下代码本人也不知道含义,不过照抄好了
5
   
#if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
6
       
WORD

wVersionRequested;
7
       
WSADATA wsaData;
8
       
int

err;
9
       
wVersionRequested=MAKEWORD(1,1);
10
       
err=WSAStartup(wVersionRequested,&wsaData);
11
       
if
(err!=0){
12
           
return
;
13
       
}
14
       
if
(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1){
15
           
WSACleanup();
16
           
return
;
17
       
}
18
   
#endif
19
 
20
   
SOCKET sockid = socket(AF_INET,SOCK_STREAM,0);
21
 
22
   
struct

sockaddr_in sockaddr;
23
   
sockaddr.sin_family = AF_INET;
24
   
//地址需要写服务器端的地址
25
   
sockaddr.sin_addr.s_addr = inet_addr(
"127.0.0.1"
);
26
   
//端口号和服务器的端口号相同
27
   
sockaddr.sin_port = htons(8888);
28
   
int

len =
sizeof
(
struct

sockaddr_in);
29
 
30
   
//客户端使用的函数是connect()
31
   
if
(connect(sockid,(
struct

sockaddr *)&sockaddr,len) == -1)
32
   
{
33
       
CCLog(
"accept error"
);
34
       
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
35
               
closesocket(sockid);
36
               
WSACleanup();
37
       
#else
38
               
close(sockid);
39
       
#endif
40
       
return
;
41
   
}
42
   
CCLog(
"client connect is ok!"
);
43
   
static

int
i = 1;
44
   
CCString * str = CCString::createWithFormat(
"%d client"
,i++);
45
   
//最后一个参数写0就可以了
46
   
int

len2 = send(sockid,str->getCString(),str->length(),0);
47
   
if
(len2 != -1)
48
   
{
49
       
CCLog(
"send %d bytes"
,len2);
50
   
}
51
   
else
52
   
{
53
       
CCLog(
"send failure!"
);
54
   
}
55
}
以上代码的含义我注释的已经非常清楚了,有不懂的可以问我,对于线程的那部分可以看看我以前的文章。在这个过程中我也走了不少的歪路,希望我们共同学习!



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: