socket编程解决网络数据的传输
2014-08-29 10:11
495 查看
socket编程我用的就是原生态的socket,今天也只是学了下原理,写了一个简单的小例子,听说websocket这个第三方库不错,这几天也想学学,看看怎么样吧。原生态的socket我第一次弄,中间出了不少的问题,我把他们都记录了下来,方便以后看吧。明天想移植到android上看看,解决一下编码的问题库的问题什么的,今天把他们的使用方法贴出来,大家可以参考一下。
查看源代码
打印帮助
以上的代码是在头文件中的申明,这里要注意不同的平台需要包含不同的头文件,thread头文件还要附加包含路径,socket要引入库。
查看源代码
打印帮助
查看源代码
打印帮助
以上代码的含义我注释的已经非常清楚了,有不懂的可以问我,对于线程的那部分可以看看我以前的文章。在这个过程中我也走了不少的歪路,希望我们共同学习!
查看源代码
打印帮助
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; |
查看源代码
打印帮助
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 | } |
相关文章推荐
- filter结合gzip 解决web应用中网络传输数据量大的问题
- filter结合gzip 解决web应用中网络传输数据量大的问题
- Java EE 下利用Servlet filter接口 和 GZIPOutputStream 包装流 解决web应用中网络传输数据量大的问题
- 关于管道的大量数据传输问题解决方法 ( vc )
- 网络数据加密需要解决三个问题:
- 在网络中传输数据(I)
- [翻译]CoolStreaming/DONet: 实时流媒体传输的数据重叠网络 (2)
- 解决TCP网络传输“粘包”问题
- 在网络中传输数据 [转]
- 使用Java实现网络传输数据的压缩.
- 使用Java实现网络传输数据的压缩
- 解决TCP网络传输“粘包”问题
- 在网络中传输数据(I)
- 基于TCP的网络游戏黑白棋系列(二):数据传输
- 通过TCPIP网络传输数据经过的三层buffer
- 关于使用DirectShow架构,传输YUV420数据的Filter与Video Renderer Filter连接问题的解决办法。
- 解决TCP网络传输“粘包”问题
- System.Net :在网络中传输数据(II) (转载)
- 网络IPC, socket(4): 数据传输函数
- [非原创]网络数据传输监控类库代码(VB6)