Posts Tagged ‘socket’

基于socket API的C/S通信:将Qt程序从Linux移植到windows

30 7 月, 2011

Qt是一个跨平台的GUI开发语言,它是对C++在图形设计方面上的一种扩充。Qt本身包含一系列用来设计图形界面的类,并且对C++原有的类都进行了再次封装。如果你的程序采用Qt的类库,那么源程序在不同平台重新编译即可;如果程序中使用某些C++或C库函数,那么在移植时就需要针对不同平台作一些改动。

本文所举例的移植代码是基于socket API的C/S模型的客户端,该客户端的原始代码在linux系统下完成(以下称为“源代码”),现在要将其移植到windows平台下(以下称“移植代码”)。源代码的界面部分采用Qt完成,而通信部分则是采用原始的socket接口。

1.加入动态库

在linux系统中,socket API属于libc库,因此只需在程序中加头文件即可。而在windows系统下,由于socket接口是继承Unix系统而来,因此需要加入wsock32库,并且加上相应的头文件winsock2.h。加入该库具体的做法是在工程问价中加入下面的语句:

LIBS += -lwsock32

2.初始化套接字库

在windows下有两套socket API,一种是经过C++封装的csocket类,而另一种则是原始的socket接口,为了降低移植的复杂性,我们采用后者。

在将wsock32动态库加入移植程序后,socket接口还不能使用,因为在这之前必须使用WSAStartup函数对该库进行初始化。具体的初始化代码可以参考如下:

    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD(1,1);

    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
     return;
    }

    if ( LOBYTE(wsaData.wVersion) != 1 ||
           HIBYTE(wsaData.wVersion) != 1 ) {
     WSACleanup();
     return;

WSAStartup函数有两个参数,wVersionRequested用来向该函数传递socket接口调用者可以使用socket的最高版本号,通过MAKEWORD宏即可完成版本号的组装,该变量的低字节指定主版本号而低字节指定次版本号。wsaData用来接收socket函数执行期间的一些数据。
当WSAStartup函数初始化动态库成功时返回0,否则返回-1。

当初始化成功后,还要再确认已加载的动态库的版本是否和我们所指定的动态库版本相吻合,如果不符合,则通过WSACleanup函数清除已加载的动态库。

动态库加载成功后,接下来就可以使用socket接口函数了,当使用完毕时,需要用WSACleanup函数卸载动态库。

3.更改套接字描述符

在使用一系列socket接口之前,必须使用socket函数创建套接字。在linux下,原始的socket函数返回的套接字描述符是整型,但是在windows下,该函数返回的套接字描述符是SOCKET类型。因此源代码和移植代码参考如下:

源代码:

    int sockfd;
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        ui->statusLabel->setText("ERROR:socket connceting fail!");
        exit(1);
    }

移植代码:

    SOCKET sockfd;
    if ((cli.sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        ui->statusLabel->setText("ERROR:socket connceting fail!");
        exit(1);
    }

既然在移植代码中套接字描述符不是整型,那么其错误返回值也应该不是-1而是标准的错误返回值INVALID_SOCKET。

4.close函数

源代码中关闭套接字选用close(),而移植程序相应的使用closesocket()。并且此时用WSACleanup()关闭已加载的动态库。

进过上述几个部分的修改,此时移植程序在windows下即可编译成功。

Linux下的socket编程-服务器

15 3 月, 2011

我们都知道,同一台计算机上的进程可以通过IPC(进程间通信)机制进行通信;而不同机算计上运行的进程则通过网络IPC,即套接字(socket)进行通信。Linux下的socket API是基于BSD套接口而是实现的,通过这些统一的API就可以轻松实现进程间的网络通信。此外,socket API即可用于面向连接(TCP)的数据传输,又可用于无连接(UDP)的数据传输。一般使用Client/Server交互模型进行通信。

本文以及下文将实现一个面向连接的C/S通信模型。本文首先介绍服务器端的实现。

1.创建套接字

#include < sys/socket.h >
int socket(int domain, int type, int protocol);

通过socket函数可以创建一个套接字描述符,这个描述符类似文件描述符。通过这个套接字描述符就可以对服务器进行各种相关操作。

该函数包含三个参数,domain参数用于指定所创建套接字的协议类型。通常选用AF_INET,表示使用IPv4的TCP/IP协议;如果只在本机内进行进程间通信,则可以使用AF_UNIX。参数type用来指定套接字的类型,SOCK_STREAM用于创建一个TCP流的套接字,SOCK_DGRAM用于创建UDP数据报套接字。参数protocol通常取0。对于本文所描述的服务器,创建套接字的示例代码如下:

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

		printf("socket error!\n");
		exit(1);
	}

2.绑定套接字

对于服务器而言,它的IP地址和端口号一般是固定的。服务器的IP即为本地IP,而服务器的端口号则需要显示的指定。通过bind函数可将服务器套接字和一个指定的端口号进行绑定。

在具体介绍绑定函数之前,先说明一下socket中的套接字地址结构。由于套接字是通过IP地址和端口号来唯一确定的,因此socket提供了一种通用的套接字地址结构:

   struct sockaddr {
               sa_family_t sa_family;
               char        sa_data[14];
           }

sa_family指定了套接字对应的协议类型,如果使用TCP/IP协议则改制为AF_INET;sa_data则用来存储具体的套接字地址。不过在实际应用中,每个具体的协议族都有自己的协议地址格式。比如TCP/IP协议组对应的套接字地址结构体为:

struct sockaddr_in {
	short int sin_family; /* Address family */
	unsigned short int sin_port; /* Port number */
	struct in_addr sin_addr; /* Internet address */
	unsigned char sin_zero[8]; /* Same size as struct sockaddr */
};

struct in_addr {
	unsigned long s_addr;
};

该地址结构和sockaddr结构均为16字节,因此通常在编写基于TCP/IP协议的网络程序时,使用sockaddr_in来设置具体地址,然后再通过强制类型转换为sockaddr类型。

绑定函数的函数原型如下:

       #include < sys/socket.h >
       int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数sockfd即服务器的套接字描述符;addr参数指定了将socket绑定到的本地地址;addrlen则为所使用的地址结构的长度。示例代码如下:

	memset(&my_addr, 0, sizeof(struct sockaddr_in));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(SERV_PORT);
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(sockfd, (struct sockaddr *)&my_addr,
				sizeof(struct sockaddr_in)) == -1) {

		printf("bind error!\n");
		exit(1);
	}

注意在上述代码中,将IP地址设置为INADDR_ANY,这样就既适合单网卡的计算机又适合多网卡的计算机。

3.在套接字上监听

对于C/S模型来说,通常是客户端主动的对服务器端发送连接请求,服务器接收到请求后再具体进行处理。服务器只有调用了listen函数才能宣告自己可以接受客户端的连接请求,也就是说,服务器此时处于被动监听状态。listen函数的原型如下:

       #include < sys/socket.h >
       int listen(int sockfd, int backlog);

sockfd为服务器端的套接字描述符,backlog指定了该服务器所能连接客户端的最大数目。超过这个连接书目后,服务器将拒绝接受客户端的连接请求。示例代码如下:

        #define BACKLOG 10
	if(listen(sockfd, BACKLOG) == -1) {

		printf("listen error!\n");
		exit(1);
	}

4.接受连接

listen函数只是将服务器套接字设置为等待客户端连接请求的状态,真正接受客户端连接请求的是accept函数:

      #include < sys/socket.h >
       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept函数中所使用的参数都在上面的API中有所描述。accept函数执行成功后将返回一个代表客户端的套接字描述符,服务器进程通过该套接字描述符就可以与客户端进行数据交换。

5.数据传输

由于socket适用多个数据传输协议,则不同的协议就对应不同的数据传输函数。与TCP协议对应的发送数据和接受数据的函数如下:

       #include < sys/socket.h >
       #include < sys/types.h >
       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

从这两个函数的原型可以看书,socket中的数据传输函数与普通文件的读写函数类似,只不过第一个参数需要传递套接字描述符;buf指定数据缓冲区;len为所传输数据的长度;flag一般取0。示例代码如下:

	while (1) {
		sin_size = sizeof(struct sockaddr_in);
		if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1) {
			printf("accept error!\n");
			continue;
		}
		/*
                 *进行相应的数据处理;
                 */
	}

如示例代码所示,通过while循环使得服务器对客户端进行持续监听。如果客户端有连接请求则新建一个代表客户端的套接字描述符,进而进行对客户端数据的接受和发送。

上述的几个函数属于网络编程中最基本的也是最关键的几个API,依次通过上述的方法就可以完成服务器端的程序的编写,具体的过程还可以参考下图:

正如上图所示,在处理完客户端的数据传输请求后,必须通过close函数关闭客户端的连接。

参考:

1.Linux C编程实战;童永清 著;人民邮电出版社;

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key