TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议。
OSI 协议参考模型,它是基于国际标准化组织(ISO)的建议发展起来的,从上到下共分为7 层:应用层、表示层、会话层、传输层、网络层、数据链路层及物理层
TCP/IP 参考模型 :从上到下共分为4 层 :应用层、传输层、网络层、网络接口层
TCP:为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求得到响应的应用程序。
UDP:提供了无连接通信,且不对传送包进行可靠的保证。适合于一次传输少量数据,可靠性则由应用层来负责。
TCP 三次握手协议
TCP对话通过三次握手来初始化的。三次握手的目的是使数据段的发送和接收同步,告诉其他主机其一次可接收的数据量,并建立虚连接。
三次握手的简单过程。
· 初始化主机通过一个同步标志置位的数据段发出会话请求。
· 接收主机通过发回具有以下项目的数据段表示回复:同步标志置位、即将发送的数据段的起始字节的顺序号、应答并带有将收到的下一个数据段的字节顺序号。
· 请求主机再回送一个数据段,并带有确认顺序号和确认号。
UDP
UDP 即用户数据报协议,它是一种无连接协议,因此不需要像TCP 那样通过三次握手来建立一个连接。同时,一个UDP应用可同时作为应用的客户或服务器方。由于UDP协议
并不需要建立一个明确的连接,因此建立UDP应用要比建立TCP应用简单得多。
socket
socket接口是一种特殊的I/O,它也是一种文件描述符。每一个socket都用一个半相关描述{协议,本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议,本地地址、本地端口、远程地址、远程端口}
socket有3 种类型
(1)流式socket(SOCK_STREAM)
流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性。
(2)数据报socket(SOCK_DGRAM)
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP。
(3)原始socket
原始套接字允许对底层协议如IP或ICMP进行直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。
地址结构相关处理
1 . 下面首先介绍两个重要的数据类型:sockaddr 和sockaddr_in,这两个结构类型都是用来保存socket信息的,如下所示:
- struct sockaddr {
- unsigned short sa_family; /*地址族*/
- char sa_data[14]; /*14字节的协议地址,包含该socket的IP地址和端口号。*/
- };
- struct sockaddr_in {
- short int sa_family; /*地址族*/
- unsigned short int sin_port; /*端口号*/
- struct in_addr sin_addr; /*IP地址*/
- unsigned char sin_zero[8]; /*填充0 以保持与struct sockaddr同样大小*/
- };
struct sockaddr { unsigned short sa_family; /*地址族*/ char sa_data[14]; /*14字节的协议地址,包含该socket的IP地址和端口号。*/ }; struct sockaddr_in { short int sa_family; /*地址族*/ unsigned short int sin_port; /*端口号*/ struct in_addr sin_addr; /*IP地址*/ unsigned char sin_zero[8]; /*填充0 以保持与struct sockaddr同样大小*/ };
这两个数据类型是等效的,可以相互转化,通常sockaddr_in数据类型使用更为方便。在建立socketadd或sockaddr_in后,就可以对该socket 进行适当的操作了。
2.结构字段
下面列出了该结构sa_family字段可选的常见值。
结构定义头文件#include <netinet/in.h>
AF_INET:IPv4协议
AF_INET6:IPv6协议
AF_LOCAL:UNIX域协议
AF_LINK:链路地址协议
Sa_family
AF_KEY:密钥套接字(socket)
htons、ntohs、htonl、ntohl。这四个地址分别实现网络字节序和主机字节序的转化,这里的h 代表host,n 代表network,s 代表short,l 代表long
3.地址格式转化函数
在IPv4 中用到的函数有inet_aton、inet_addr 和inet_ntoa,而IPv4 和IPv6 兼容的函数有inet_pton 和inet_ntop。在IPv4 中用到的函数有inet_aton、inet_addr 和inet_ntoa,而IPv4 和IPv6 兼容的函数有inet_pton 和inet_ntop。
inet_pton 函数是将点分十进制地址映射为二进制地址,而inet_ntop 是将二进制地址映射为点分十进制地址。
函数原型如下:
int inet_pton(int family,const char *strptr, void *addrptr) strptr:要转化的值 addrptr:转化后的地址
int inet_ntop(int family, void *addrptr, char *strptr, size_t len) addrptr:转化后的地址 strptr:要转化的值
4.名字地址转化
一些函数可以实现主机名和地址的转化,最为常见的有gethostbyname、gethostbyaddr、getaddrinfo等
gethostbyname 是将主机名转化为IP 地址,gethostbyaddr 则是逆操作,是将IP地址转化为主机名,另外getaddrinfo还能实现自动识别IPv4地址和IPv6地址。
gethostbyname和gethostbyaddr 都涉及到一个hostent 的结构体
- Struct hostent{
- char *h_name;/*正式主机名*/
- char **h_aliases;/*主机别名*/
- int h_addrtype;/*地址类型*/
- int h_length;/*地址长度*/
- char **h_addr_list;/*指向IPv4或IPv6的地址指针数组*/
- }
Struct hostent{ char *h_name;/*正式主机名*/ char **h_aliases;/*主机别名*/ int h_addrtype;/*地址类型*/ int h_length;/*地址长度*/ char **h_addr_list;/*指向IPv4或IPv6的地址指针数组*/ }
调用该函数后就能返回hostent 结构体的相关信息。
- struct addrinfo{
- int ai_flags;/*AI_PASSIVE,AI_CANONNAME;*/
- int ai_family;/*地址族*/
- int ai_socktype;/*socket类型*/
- int ai_protocol;/*协议类型*/
- size_t ai_addrlen;/*地址长度*/
- char *ai_canoname;/*主机名*/
- struct sockaddr *ai_addr;/*socket结构体*/
- struct addrinfo *ai_next;/*下一个指针链表*/
- }
struct addrinfo{ int ai_flags;/*AI_PASSIVE,AI_CANONNAME;*/ int ai_family;/*地址族*/ int ai_socktype;/*socket类型*/ int ai_protocol;/*协议类型*/ size_t ai_addrlen;/*地址长度*/ char *ai_canoname;/*主机名*/ struct sockaddr *ai_addr;/*socket结构体*/ struct addrinfo *ai_next;/*下一个指针链表*/ }
getaddrinfo函数涉及到一个addrinfo的结构体
头文件: #include <netdb.h>
函数原型
Struct hostent *gethostbyname(const char *hostname) Hostname:主机名
Int getaddrinfo(const char *hostname,const char *service,const struct addrinfo*hints,struct addrinfo **result) service:服务名或十进制的串口号字符串 hints:服务线索 result:返回结果
----------- socket基础编程
socket编程的基本函数有socket、bind、listen、accept、send、sendto、recv、recvfrom这几个
· socket:该函数用于建立一个socket连接,可指定socket类型等信息。在建立了socket连接之后,可对socketadd或sockaddr_in进行初始化,以保存所建立的socket信息。
· bind:该函数是用于将本地IP 地址绑定端口号的,若绑定其他地址则不能成功。另外,它主要用于TCP的连接,而在UDP的连接中则无必要。
· connect:该函数在TCP中是用于bind的之后的client 端,用于与服务器端建立连接,而在UDP中由于没有了bind函数,因此用connect有点类似bind函数的作用。
· send和recv:这两个函数用于接收和发送数据,可以用在TCP中,也可以用在UDP中。当用在UDP时,可以在connect函数建立连接之后再用。
· sendto和recvfrom:这两个函数的作用与send和recv函数类型,也可以用在TCP和UDP中。当用在TCP时,后面的几个与地址有关参数不起作用,函数作用等同于send和recv;当用在UDP时,可以用在之前没有使用connect的情况时,这两个函数可以自动寻找制定地址并进行连接。
用TCP协议socket编程流程图
用UDP协议socket编程流程图
函数格式
所需头文件#include <sys/socket.h>
函数原型int socket(int family, int type, int protocol)
family:协议族 type:套接字类型:SOCK_STREAM:字节流套接字socket SOCK_DGRAM:数据报套接字socket SOCK_RAW:原始套接字socket
函数原型int bind(int sockfd,struct sockaddr *my_addr, int addrlen) socktd:套接字描述符 my_addr:本地地址 addrlen:地址长度
函数原型int listen(int sockfd, int backlog) Backlog:请求队列中允许的最大请求数,大多数系统缺省值为20
函数原型int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) addr:客户端地址 addrlen:地址长度
函数原型int connect(int sockfd, struct sockaddr *serv_addr, int addrlen) serv_addr:服务器端地址 addrlen:地址长度
函数原型int send(int sockfd, const void *msg, int len, int flags) msg:指向要发送数据的指针 len:数据长度 flags:一般为0
函数原型int recv(int sockfd,void *buf,int len,unsigned int flags)
函数原型int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr*to, int tolen)
函数原型int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int*fromlen) from:源机的IP地址和端口号信息 tolen:地址长度
一个简单的C/S例子
server.c
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #define SERVPORT 3333
- #define BACKLOG 10
- #define MAX_CONNECTED_NO 10
- #define MAXDATASIZE 5
- int main()
- {
- struct sockaddr_in server_sockaddr,client_sockaddr;
- int sin_size,recvbytes;
- int sockfd,client_fd;
- char buf[MAXDATASIZE];
- /*建立socket连接*/
- if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){
- perror("socket");
- exit(1);
- }
- printf("socket success!,sockfd=%d\n",sockfd);
- /*设置sockaddr_in 结构体中相关参数*/
- server_sockaddr.sin_family=AF_INET;
- server_sockaddr.sin_port=htons(SERVPORT);
- server_sockaddr.sin_addr.s_addr=INADDR_ANY;
- bzero(&(server_sockaddr.sin_zero),8);
- /*绑定函数bind*/
- if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct
- sockaddr))== -1){
- perror("bind");
- exit(1);
- }
- printf("bind success!\n");
- /*调用listen函数*/
- if(listen(sockfd,BACKLOG)== -1){
- perror("listen");
- exit(1);
- }
- printf("listening....\n");
- /*调用accept函数,等待客户端的连接*/
- if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_
- size))== -1){
- perror("accept");
- exit(1);
- }
- /*调用recv函数接收客户端的请求*/
- if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))== -1){
- perror("recv");
- exit(1);
- }
- printf("received a connection :%s\n",buf);
- close(sockfd);
- }
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #define SERVPORT 3333 #define BACKLOG 10 #define MAX_CONNECTED_NO 10 #define MAXDATASIZE 5 int main() { struct sockaddr_in server_sockaddr,client_sockaddr; int sin_size,recvbytes; int sockfd,client_fd; char buf[MAXDATASIZE]; /*建立socket连接*/ if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){ perror("socket"); exit(1); } printf("socket success!,sockfd=%d\n",sockfd); /*设置sockaddr_in 结构体中相关参数*/ server_sockaddr.sin_family=AF_INET; server_sockaddr.sin_port=htons(SERVPORT); server_sockaddr.sin_addr.s_addr=INADDR_ANY; bzero(&(server_sockaddr.sin_zero),8); /*绑定函数bind*/ if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))== -1){ perror("bind"); exit(1); } printf("bind success!\n"); /*调用listen函数*/ if(listen(sockfd,BACKLOG)== -1){ perror("listen"); exit(1); } printf("listening....\n"); /*调用accept函数,等待客户端的连接*/ if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_ size))== -1){ perror("accept"); exit(1); } /*调用recv函数接收客户端的请求*/ if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))== -1){ perror("recv"); exit(1); } printf("received a connection :%s\n",buf); close(sockfd); }
client.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #define SERVPORT 3333
- #define MAXDATASIZE 100
- main(int argc,char *argv[]){
- int sockfd,sendbytes;
- char buf[MAXDATASIZE];
- struct hostent *host;
- struct sockaddr_in serv_addr;
- if(argc < 2){
- fprintf(stderr,"Please enter the server's hostname!\n");
- exit(1);
- }
- /*地址解析函数*/
- if((host=gethostbyname(argv[1]))==NULL){
- perror("gethostbyname");
- exit(1);
- }
- /*创建socket*/
- if((sockfd=socket(AF_INET,SOCK_STREAM,0))== -1){
- perror("socket");
- exit(1);
- }
- /*设置sockaddr_in 结构体中相关参数*/
- serv_addr.sin_family=AF_INET;
- serv_addr.sin_port=htons(SERVPORT);
- serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
- bzero(&(serv_addr.sin_zero),8);
- /*调用connect函数主动发起对服务器端的连接*/
- if(connect(sockfd,(struct sockaddr *)&serv_addr,\
- sizeof(struct sockaddr))== -1){
- perror("connect");
- exit(1);
- }
- /*发送消息给服务器端*/
- if((sendbytes=send(sockfd,"hello",5,0))== -1){
- perror("send");
- exit(1);
- }
- close(sockfd);
- }
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define SERVPORT 3333 #define MAXDATASIZE 100 main(int argc,char *argv[]){ int sockfd,sendbytes; char buf[MAXDATASIZE]; struct hostent *host; struct sockaddr_in serv_addr; if(argc < 2){ fprintf(stderr,"Please enter the server's hostname!\n"); exit(1); } /*地址解析函数*/ if((host=gethostbyname(argv[1]))==NULL){ perror("gethostbyname"); exit(1); } /*创建socket*/ if((sockfd=socket(AF_INET,SOCK_STREAM,0))== -1){ perror("socket"); exit(1); } /*设置sockaddr_in 结构体中相关参数*/ serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(SERVPORT); serv_addr.sin_addr=*((struct in_addr *)host->h_addr); bzero(&(serv_addr.sin_zero),8); /*调用connect函数主动发起对服务器端的连接*/ if(connect(sockfd,(struct sockaddr *)&serv_addr,\ sizeof(struct sockaddr))== -1){ perror("connect"); exit(1); } /*发送消息给服务器端*/ if((sendbytes=send(sockfd,"hello",5,0))== -1){ perror("send"); exit(1); } close(sockfd); }
网络高级编程网络高级编程所需头文件 #include <sys/socket.h>
函数原型int socket(int family, int type, int protocol)所需头文件#include <sys/socket.h>
函数原型int socket(int family, int type, int protocol)所需头文件#include <sys/socket.h>
函数原型int socket(int family, int type, int protocol)调用该函数后就能返回hostent 结构体的相关信息。
getaddrinfo函数涉及到一个addrinfo的结构体调用该函数后就能返回hostent 结构体的相关信息。
getaddrinfo函数涉及到一个addrinfo的结构体
5.网络高级编程
之前介绍的如connet、recv、send都是阻塞性函数,若资源没有准备好,则调用该函数的进程将进入睡眠状态,这样就无法处理I/O 多路复用的情况了,fcntl和select是了两种解决I/O 多路复用的解决方法
1.fcntl
函数fcntl针对socket编程提供了如下的编程特性。
· 非阻塞I/O:可将cmd设置为F_SETFL,将lock设置为O_NONBLOCK。
· 信号驱动I/O:可将cmd设置为F_SETFL,将lock设置为O_ASYNC。
简单的例子fcntl.c
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/un.h>
- #include <sys/time.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <fcntl.h>
- #define SERVPORT 3333
- #define BACKLOG 10
- #define MAX_CONNECTED_NO 10
- #define MAXDATASIZE 100
- int main()
- {
- struct sockaddr_in server_sockaddr,client_sockaddr;
- int sin_size,recvbytes,flags;
- int sockfd,client_fd;
- char buf[MAXDATASIZE];
- if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){
- perror("socket");
- exit(1);
- }
- printf("socket success!,sockfd=%d\n",sockfd);
- server_sockaddr.sin_family=AF_INET;
- server_sockaddr.sin_port=htons(SERVPORT);
- server_sockaddr.sin_addr.s_addr=INADDR_ANY;
- bzero(&(server_sockaddr.sin_zero),8);
- if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct
- sockaddr))== -1){
- perror("bind");
- exit(1);
- }
- printf("bind success!\n");
- if(listen(sockfd,BACKLOG)== -1){
- perror("listen");
- exit(1);
- }
- printf("listening....\n");
- /*调用fcntl函数设置非阻塞参数*/
- if((flags=fcntl( sockfd, F_SETFL, 0))<0)
- perror("fcntl F_SETFL");
- flag |= O_NONBLOCK;
- if(fcntl(fd,F_SETEL,flags)<0)
- perror("fcntl");
- while(1){
- sin_size=sizeof(struct sockaddr_in);
- if((client_fd=accept(sockfd,(structsockaddr*)&client_sockaddr,
- &sin_size))== -1){
- perror("accept");
- exit(1);
- }
- if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))== -1){
- perror("recv");
- exit(1);
- }
- if(read(client_fd,buf,MAXDATASIZE)<0){
- perror("read");
- exit(1);
- }
- printf("received a connection :%s",buf);
- close(client_fd);
- exit(1);
- }/*while*/
- }
#include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/un.h> #include <sys/time.h> #include <sys/ioctl.h> #include <unistd.h> #include <netinet/in.h> #include <fcntl.h> #define SERVPORT 3333 #define BACKLOG 10 #define MAX_CONNECTED_NO 10 #define MAXDATASIZE 100 int main() { struct sockaddr_in server_sockaddr,client_sockaddr; int sin_size,recvbytes,flags; int sockfd,client_fd; char buf[MAXDATASIZE]; if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){ perror("socket"); exit(1); } printf("socket success!,sockfd=%d\n",sockfd); server_sockaddr.sin_family=AF_INET; server_sockaddr.sin_port=htons(SERVPORT); server_sockaddr.sin_addr.s_addr=INADDR_ANY; bzero(&(server_sockaddr.sin_zero),8); if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))== -1){ perror("bind"); exit(1); } printf("bind success!\n"); if(listen(sockfd,BACKLOG)== -1){ perror("listen"); exit(1); } printf("listening....\n"); /*调用fcntl函数设置非阻塞参数*/ if((flags=fcntl( sockfd, F_SETFL, 0))<0) perror("fcntl F_SETFL"); flag |= O_NONBLOCK; if(fcntl(fd,F_SETEL,flags)<0) perror("fcntl"); while(1){ sin_size=sizeof(struct sockaddr_in); if((client_fd=accept(sockfd,(structsockaddr*)&client_sockaddr, &sin_size))== -1){ perror("accept"); exit(1); } if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))== -1){ perror("recv"); exit(1); } if(read(client_fd,buf,MAXDATASIZE)<0){ perror("read"); exit(1); } printf("received a connection :%s",buf); close(client_fd); exit(1); }/*while*/ }
2.select
使用fcntl 函数虽然可以实现非阻塞I/O 或信号驱动I/O,但在实际使用时往往会对资源是否准备完毕进行循环测试,这样就大大增加了不必要的CPU 资源。select函数还可以设置等待的时
select_socket.c
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/un.h>
- #include <sys/time.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #define SERVPORT 3333
- #define BACKLOG 10
- #define MAX_CONNECTED_NO 10
- #define MAXDATASIZE 100
- int main()
- {
- struct sockaddr_in server_sockaddr,client_sockaddr;
- int sin_size,recvbytes;
- fd_set readfd;
- fd_set writefd;
- int sockfd,client_fd;
- char buf[MAXDATASIZE];
- if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){
- perror("socket");
- exit(1);
- }
- printf("socket success!,sockfd=%d\n",sockfd);
- server_sockaddr.sin_family=AF_INET;
- server_sockaddr.sin_port=htons(SERVPORT);
- server_sockaddr.sin_addr.s_addr=INADDR_ANY;
- bzero(&(server_sockaddr.sin_zero),8);
- if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct
- sockaddr))== -1){
- perror("bind");
- exit(1);
- }
- printf("bind success!\n");
- if(listen(sockfd,BACKLOG)== -1){
- perror("listen");
- exit(1);
- }
- printf("listening....\n");
- /*将调用socket函数的描述符作为文件描述符*/
- FD_ZERO(&readfd);
- FD_SET(sockfd,&readfd);
- while(1){
- sin_size=sizeof(struct sockaddr_in);
- /*调用select函数*/
- if(select(MAX_CONNECTED_NO,&readfd,NULL,NULL,(struct timeval *)0)>0){
- if(FD_ISSET(sockfd,&readfd)>0){
- if((client_fd=accept(sockfd,(struct sockaddr *)&client_
- sockaddr,&sin_size))== -1){
- perror("accept");
- exit(1);
- }
- if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))== -1){
- perror("recv");
- exit(1);
- }
- if(read(client_fd,buf,MAXDATASIZE)<0){
- perror("read");
- exit(1);
- }
- printf("received a connection :%s",buf);
- }/*if*/
- close(client_fd);
- }/*select*/
- }/*while*/
- }
#include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/un.h> #include <sys/time.h> #include <sys/ioctl.h> #include <unistd.h> #include <netinet/in.h> #define SERVPORT 3333 #define BACKLOG 10 #define MAX_CONNECTED_NO 10 #define MAXDATASIZE 100 int main() { struct sockaddr_in server_sockaddr,client_sockaddr; int sin_size,recvbytes; fd_set readfd; fd_set writefd; int sockfd,client_fd; char buf[MAXDATASIZE]; if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){ perror("socket"); exit(1); } printf("socket success!,sockfd=%d\n",sockfd); server_sockaddr.sin_family=AF_INET; server_sockaddr.sin_port=htons(SERVPORT); server_sockaddr.sin_addr.s_addr=INADDR_ANY; bzero(&(server_sockaddr.sin_zero),8); if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))== -1){ perror("bind"); exit(1); } printf("bind success!\n"); if(listen(sockfd,BACKLOG)== -1){ perror("listen"); exit(1); } printf("listening....\n"); /*将调用socket函数的描述符作为文件描述符*/ FD_ZERO(&readfd); FD_SET(sockfd,&readfd); while(1){ sin_size=sizeof(struct sockaddr_in); /*调用select函数*/ if(select(MAX_CONNECTED_NO,&readfd,NULL,NULL,(struct timeval *)0)>0){ if(FD_ISSET(sockfd,&readfd)>0){ if((client_fd=accept(sockfd,(struct sockaddr *)&client_ sockaddr,&sin_size))== -1){ perror("accept"); exit(1); } if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))== -1){ perror("recv"); exit(1); } if(read(client_fd,buf,MAXDATASIZE)<0){ perror("read"); exit(1); } printf("received a connection :%s",buf); }/*if*/ close(client_fd); }/*select*/ }/*while*/ }
下面是实现简单的linux 下的TCP通讯程序
服务器端的代码如下:
server.c
- <P>#include<stdio.h>
- #include<stdlib.h>
- #include<errno.h>
- #include<string.h>
- #include<sys/types.h>
- #include<netinet/in.h>
- #include<sys/socket.h>
- #include<sys/wait.h>
- #include<pthread.h></P><P>#define MYPORT 3490
- #define BACKLOG 10
- #define MAXDATASIZE 1024</P><P>int sockfd,new_fd;
- pthread_t accthread,recthread;</P><P>void recmessage(void){
- while(1){
- int numbytes;
- char buf[MAXDATASIZE];
- if((numbytes = recv(new_fd,buf,MAXDATASIZE,0)) == -1){
- perror("recv");
- exit(1);
- }
- buf[numbytes] = '\0';
- if(strcmp(buf,"exit") == 0){
- printf("Client is closed\n");
- close(new_fd);
- close(sockfd);
- exit(1);
- }
- printf("Client:%s\n",buf);
- }
- }</P><P>
- void acceptconnect(void){
- struct sockaddr_in their_addr;
- int sin_size;
- sin_size = sizeof(struct sockaddr_in);
- if((new_fd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size)) == -1){
- perror("accept");
- exit(1);
- }
- printf("server:got connection from %s\n",inet_ntoa(their_addr.sin_addr));
- if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!= 0){
- printf("Create thread error!\r\n");
- exit(1);
- }
- }
- int main(void){
- struct sockaddr_in my_addr;
- if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
- perror("socket");
- exit(1);
- }
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(MYPORT);
- my_addr.sin_addr.s_addr = INADDR_ANY;
- bzero(&(my_addr.sin_zero),8);
- if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1){
- perror("bind");
- exit(1);
- }
- if(listen(sockfd,BACKLOG) == -1){
- perror("listen");
- exit(1);
- }
- if((pthread_create(&accthread,NULL,(void *)acceptconnect,NULL)) != 0){
- printf("Create thread error!\r\n");
- exit(1);
- }
- while(1){
- char msg[MAXDATASIZE];
- scanf("%s",msg);
- if(send(new_fd,msg,strlen(msg),0) == -1){
- perror("send");
- close(new_fd);
- exit(1);
- }
- if(strcmp(msg,"exit") == 0){
- printf("Byebye!\n");
- close(new_fd);
- close(sockfd);
- exit(1);
- }
- }
- return 0;
- }
- </P>
#include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<sys/types.h> #include<netinet/in.h> #include<sys/socket.h> #include<sys/wait.h> #include<pthread.h>
#define MYPORT 3490 #define BACKLOG 10 #define MAXDATASIZE 1024
int sockfd,new_fd; pthread_t accthread,recthread;
void recmessage(void){ while(1){ int numbytes; char buf[MAXDATASIZE]; if((numbytes = recv(new_fd,buf,MAXDATASIZE,0)) == -1){ perror("recv"); exit(1); } buf[numbytes] = '\0'; if(strcmp(buf,"exit") == 0){ printf("Client is closed\n"); close(new_fd); close(sockfd); exit(1); } printf("Client:%s\n",buf); } }
void acceptconnect(void){ struct sockaddr_in their_addr; int sin_size; sin_size = sizeof(struct sockaddr_in); if((new_fd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size)) == -1){ perror("accept"); exit(1); } printf("server:got connection from %s\n",inet_ntoa(their_addr.sin_addr)); if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!= 0){ printf("Create thread error!\r\n"); exit(1); } } int main(void){ struct sockaddr_in my_addr; if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){ perror("socket"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = INADDR_ANY; bzero(&(my_addr.sin_zero),8); if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1){ perror("bind"); exit(1); } if(listen(sockfd,BACKLOG) == -1){ perror("listen"); exit(1); } if((pthread_create(&accthread,NULL,(void *)acceptconnect,NULL)) != 0){ printf("Create thread error!\r\n"); exit(1); } while(1){ char msg[MAXDATASIZE]; scanf("%s",msg); if(send(new_fd,msg,strlen(msg),0) == -1){ perror("send"); close(new_fd); exit(1); } if(strcmp(msg,"exit") == 0){ printf("Byebye!\n"); close(new_fd); close(sockfd); exit(1); } } return 0; }
客户端的代码
client.c
- #include<stdio.h>
- #include<stdlib.h>
- #include<errno.h>
- #include<string.h>
- #include<netdb.h>
- #include<sys/types.h>
- #include<netinet/in.h>
- #include<sys/socket.h>
- #include<pthread.h>
- #define PORT 3490
- #define MAXDATASIZE 1024
- int sockfd;
- pthread_t recthread;
- void recmessage(void){
- while(1){
- int numbytes;
- char buf[MAXDATASIZE];
- if((numbytes = recv(sockfd,buf,MAXDATASIZE,0)) == -1){
- perror("recv");
- exit(1);
- }
- buf[numbytes]='\0';
- if(strcmp(buf,"exit") == 0){
- printf("Server is closed\n");
- close(sockfd);
- exit(1);
- }
- printf("Server:%s\n",buf);
- }
- }
- int main(int argc,char *argv[]){
- struct hostent *host;
- struct sockaddr_in their_addr;
- if(argc != 2){
- fprintf(stderr,"usage:client hostname\n");
- exit(1);
- }
- /* 使用hostname查询host 名字 */
- if((host=gethostbyname(argv[1])) == NULL){
- herror("gethostbyname");
- exit(1);
- }
- // AF_INET:Internet;SOCK_STREAM:TCP
- /* 客户程序开始建立 sockfd描述符 */
- if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
- perror("socket");
- exit(1);
- }
- // 初始化,置0
- bzero(&(their_addr.sin_zero),8);
- // IPV4
- their_addr.sin_family = AF_INET;
- // (将本机器上的short数据转化为网络上的short数据)端口号
- their_addr.sin_port = htons(PORT);
- // IP地址
- their_addr.sin_addr = *((struct in_addr *)host->h_addr);
- /* 客户程序发起连接请求 */
- if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1){
- perror("connect");
- exit(1);
- }
- /* 连接成功了 */
- printf("connect sucess!!!:\n");
- if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!=0){
- printf("Create thread error!\r\n");
- exit(1);
- }
- while(1){
- char msg[MAXDATASIZE];
- scanf("%s",msg);
- if(send(sockfd,msg,strlen(msg),0) == -1){
- perror("send");
- close(sockfd);
- exit(1);
- }
- if(strcmp(msg,"exit") == 0){
- printf("Byebye!\n");
- /* 结束通讯 */
- close(sockfd);
- exit(1);
- }
- }
- return 0;
- }
#include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<netdb.h> #include<sys/types.h> #include<netinet/in.h> #include<sys/socket.h> #include<pthread.h> #define PORT 3490 #define MAXDATASIZE 1024 int sockfd; pthread_t recthread; void recmessage(void){ while(1){ int numbytes; char buf[MAXDATASIZE]; if((numbytes = recv(sockfd,buf,MAXDATASIZE,0)) == -1){ perror("recv"); exit(1); } buf[numbytes]='\0'; if(strcmp(buf,"exit") == 0){ printf("Server is closed\n"); close(sockfd); exit(1); } printf("Server:%s\n",buf); } } int main(int argc,char *argv[]){ struct hostent *host; struct sockaddr_in their_addr; if(argc != 2){ fprintf(stderr,"usage:client hostname\n"); exit(1); } /* 使用hostname查询host 名字 */ if((host=gethostbyname(argv[1])) == NULL){ herror("gethostbyname"); exit(1); } // AF_INET:Internet;SOCK_STREAM:TCP /* 客户程序开始建立 sockfd描述符 */ if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){ perror("socket"); exit(1); } // 初始化,置0 bzero(&(their_addr.sin_zero),8); // IPV4 their_addr.sin_family = AF_INET; // (将本机器上的short数据转化为网络上的short数据)端口号 their_addr.sin_port = htons(PORT); // IP地址 their_addr.sin_addr = *((struct in_addr *)host->h_addr); /* 客户程序发起连接请求 */ if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1){ perror("connect"); exit(1); } /* 连接成功了 */ printf("connect sucess!!!:\n"); if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!=0){ printf("Create thread error!\r\n"); exit(1); } while(1){ char msg[MAXDATASIZE]; scanf("%s",msg); if(send(sockfd,msg,strlen(msg),0) == -1){ perror("send"); close(sockfd); exit(1); } if(strcmp(msg,"exit") == 0){ printf("Byebye!\n"); /* 结束通讯 */ close(sockfd); exit(1); } } return 0; }
在终端下输入的命令: gcc server.c -lpthread -o server
./server
打开新的终端输入命令: gcc client.c -lpthread -o client
./client 127.0.0.1(要通信的IP地址,这里用的是网络的虚拟IP地址)
然后呢,还有一个SDL版本的图形界面
clientsdl.c
- #include<stdlib.h>
- #include "SDL/SDL.h"
- #include<stdio.h>
- #include<errno.h>
- #include<string.h>
- #include<netdb.h>
- #include<sys/types.h>
- #include<netinet/in.h>
- #include<sys/socket.h>
- #include<pthread.h>
- #define PORT 3490
- #define MAXDATASIZE 1024
- int sockfd;
- pthread_t recthread;
- SDL_Surface * screen;
- SDL_Surface * image;
- SDL_Event event;
- int drawsreen();
- int init_SDL();
- int event_test();
- void recmessage(void){
- while(1){
- static int i=5;
- int numbytes;
- char buf[MAXDATASIZE];
- if((numbytes = recv(sockfd,buf,MAXDATASIZE,0)) == -1){
- perror("recv");
- exit(1);
- }
- buf[numbytes]='\0';
- if(strcmp(buf,"exit") == 0){
- printf("Server is closed\n"); close(sockfd);
- exit(1);
- }
- i=i+10;
- printf("鏈嶅姟鍣ㄧ璇?%s\n",buf);
- if(i>300){
- drawsreen();
- i=0;
- stringColor(screen, 40, i, "server said:\t\t", 0x000000FF);
- stringColor(screen, 200, i, buf, 0xFFFFFF);
- SDL_UpdateRect(screen, 0, 0,0,0);
- }else{
- stringColor(screen, 40, i, "server said:\t\t", 0x000000FF);
- stringColor(screen, 200, i, buf, 0xFFFFFF);
- SDL_UpdateRect(screen, 0, 0,0,0);
- }
- }
- }
- int main(int argc,char *argv[]){
- init_SDL();
- drawsreen();
- struct hostent *host;
- struct sockaddr_in their_addr;
- if(argc != 2){
- fprintf(stderr,"璇疯緭鍏ュ鎴风殑IP鍦板潃\n");
- stringColor(screen, 40, 0, "please input the client address!!\n",0x000000FF);
- exit(1);
- }
- /* 浣跨敤hostname鏌ヨhost 鍚嶅瓧 */
- if((host=gethostbyname(argv[1])) == NULL){
- herror("娌℃湁鏌ュ埌鐩稿搴旂殑涓绘満鍚嶏紒\n");
- exit(1);
- }
- // AF_INET:Internet;SOCK_STREAM:TCP
- /* 瀹㈡埛绋嬪簭寮€濮嬪缓绔?sockfd鎻忚堪绗?*/
- if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
- perror("socket閫氫俊鍑虹幇寮傚父锛侊紒");
- exit(1);
- }
- // 鍒濆鍖?缃?
- bzero(&(their_addr.sin_zero),8);
- // IPV4
- their_addr.sin_family = AF_INET;
- // (灏嗘湰鏈哄櫒涓婄殑short鏁版嵁杞寲涓虹綉缁滀笂鐨剆hort鏁版嵁)绔彛鍙?
- their_addr.sin_port = htons(PORT);
- // IP鍦板潃
- their_addr.sin_addr = *((struct in_addr *)host->h_addr);
- /* 瀹㈡埛绋嬪簭鍙戣捣杩炴帴璇锋眰 */
- if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1){
- perror("杩炴帴澶辫触锛侊紒");
- exit(1);
- }
- SDL_UpdateRect(screen, 0, 0,0,0);
- /* 杩炴帴鎴愬姛浜?*/
- printf("杩炴帴鎴愬姛!!!:\n");
- if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!=0){
- printf("鍒涘缓thread澶辫触!\r\n");
- exit(1);
- }
- while(1){
- char msg[MAXDATASIZE];
- scanf("%s",msg);
- if(send(sockfd,msg,strlen(msg),0) == -1){
- perror("鍙戦€佷俊鎭け璐ワ紒锛?);
- close(sockfd);
- exit(1);
- SDL_UpdateRect(screen, 0, 0,0,0);
- }
- if(strcmp(msg,"exit") == 0){
- printf("Byebye!\n");
- /* 缁撴潫閫氳 */
- close(sockfd);
- exit(1);
- }
- }
- return 0;
- event_test();
- }
- int drawsreen(){
- image = SDL_LoadBMP("./bg.bmp");
- if (image == NULL) {
- fprintf(stderr, "涓嶈兘涓嬭浇鍥剧墖, %s\n", SDL_GetError());
- return -1;
- }
- if (SDL_BlitSurface(image, NULL, screen, NULL) < 0) {
- //瑙i噴涓€涓婲ULL锛岀涓€涓槸鎸夌収image鐨勫昂瀵告樉绀猴紝绗簩涓槸榛樿鏄剧ず
- fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError());
- return -1;
- }
- boxColor(screen, 10, 320,50, 360,0xff8f66);
- boxColor(screen, 60, 320,100, 360,0xff8f66);
- boxColor(screen, 110, 320,150, 360,0xff8f66);
- boxColor(screen, 160, 320,200, 360,0xff8f66);
- boxColor(screen, 210, 320,250, 360,0xff8f66);
- boxColor(screen, 260, 320,300, 360,0xff8f66);
- boxColor(screen, 310, 320,350, 360,0xff8f66);
- boxColor(screen, 360, 320,400, 360,0xff8f66);
- boxColor(screen, 410, 320,450, 360,0xff8f66);
- boxColor(screen, 460, 320,500, 360,0xff8f66);
- stringColor(screen, 30, 340,"Q",0x000000FF);
- stringColor(screen, 80, 340,"W",0x000000FF);
- stringColor(screen, 130, 340,"E",0x000000FF);
- stringColor(screen, 180, 340,"R",0x000000FF);
- stringColor(screen, 230, 340,"T",0x000000FF);
- stringColor(screen, 280, 340,"Y",0x000000FF);
- stringColor(screen, 330, 340,"U",0x000000FF);
- stringColor(screen, 380, 340,"I",0x000000FF);
- stringColor(screen, 430, 340,"O",0x000000FF);
- stringColor(screen, 480, 340,"P",0x000000FF);
- SDL_UpdateRect(screen, 0, 0, 0, 0);
- }
- int init_SDL(){
- //鍒濆鍖朣DL
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) {
- fprintf(stderr, "init SDL %s\n", SDL_GetError());
- return -1;
- }
- atexit(SDL_Quit);
- screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
- if (screen == NULL) {
- fprintf(stderr, "涓嶈兘璁剧疆 640x480x8 video mode %s\n",SDL_GetError());
- return -1;
- }
- SDL_WM_SetCaption("TCP鑱婂ぉ绋嬪簭娴嬭瘯", NULL);
- }
- int event_test(){
- while ( SDL_WaitEvent(&event) >= 0 ) {
- switch (event.type) {
- case SDL_MOUSEBUTTONDOWN:
- printf("hello,world!!!");
- SDL_UpdateRect(screen, 0, 0,0,0);
- exit(0);
- break;
- case SDL_QUIT: {
- printf("Quit requested, quitting.\n");
- exit(0);
- }
- break;
- }
- }
- }
#include<stdlib.h> #include "SDL/SDL.h" #include<stdio.h> #include<errno.h> #include<string.h> #include<netdb.h> #include<sys/types.h> #include<netinet/in.h> #include<sys/socket.h> #include<pthread.h> #define PORT 3490 #define MAXDATASIZE 1024 int sockfd; pthread_t recthread; SDL_Surface * screen; SDL_Surface * image; SDL_Event event; int drawsreen(); int init_SDL(); int event_test(); void recmessage(void){ while(1){ static int i=5; int numbytes; char buf[MAXDATASIZE]; if((numbytes = recv(sockfd,buf,MAXDATASIZE,0)) == -1){ perror("recv"); exit(1); } buf[numbytes]='\0'; if(strcmp(buf,"exit") == 0){ printf("Server is closed\n"); close(sockfd); exit(1); } i=i+10; printf("鏈嶅姟鍣ㄧ璇?%s\n",buf); if(i>300){ drawsreen(); i=0; stringColor(screen, 40, i, "server said:\t\t", 0x000000FF); stringColor(screen, 200, i, buf, 0xFFFFFF); SDL_UpdateRect(screen, 0, 0,0,0); }else{ stringColor(screen, 40, i, "server said:\t\t", 0x000000FF); stringColor(screen, 200, i, buf, 0xFFFFFF); SDL_UpdateRect(screen, 0, 0,0,0); } } } int main(int argc,char *argv[]){ init_SDL(); drawsreen(); struct hostent *host; struct sockaddr_in their_addr; if(argc != 2){ fprintf(stderr,"璇疯緭鍏ュ鎴风殑IP鍦板潃\n"); stringColor(screen, 40, 0, "please input the client address!!\n",0x000000FF); exit(1); } /* 浣跨敤hostname鏌ヨhost 鍚嶅瓧 */ if((host=gethostbyname(argv[1])) == NULL){ herror("娌℃湁鏌ュ埌鐩稿搴旂殑涓绘満鍚嶏紒\n"); exit(1); } // AF_INET:Internet;SOCK_STREAM:TCP /* 瀹㈡埛绋嬪簭寮€濮嬪缓绔?sockfd鎻忚堪绗?*/ if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){ perror("socket閫氫俊鍑虹幇寮傚父锛侊紒"); exit(1); } // 鍒濆鍖?缃? bzero(&(their_addr.sin_zero),8); // IPV4 their_addr.sin_family = AF_INET; // (灏嗘湰鏈哄櫒涓婄殑short鏁版嵁杞寲涓虹綉缁滀笂鐨剆hort鏁版嵁)绔彛鍙? their_addr.sin_port = htons(PORT); // IP鍦板潃 their_addr.sin_addr = *((struct in_addr *)host->h_addr); /* 瀹㈡埛绋嬪簭鍙戣捣杩炴帴璇锋眰 */ if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1){ perror("杩炴帴澶辫触锛侊紒"); exit(1); } SDL_UpdateRect(screen, 0, 0,0,0); /* 杩炴帴鎴愬姛浜?*/ printf("杩炴帴鎴愬姛!!!:\n"); if((pthread_create(&recthread,NULL,(void *)recmessage,NULL))!=0){ printf("鍒涘缓thread澶辫触!\r\n"); exit(1); } while(1){ char msg[MAXDATASIZE]; scanf("%s",msg); if(send(sockfd,msg,strlen(msg),0) == -1){ perror("鍙戦€佷俊鎭け璐ワ紒锛?); close(sockfd); exit(1); SDL_UpdateRect(screen, 0, 0,0,0); } if(strcmp(msg,"exit") == 0){ printf("Byebye!\n"); /* 缁撴潫閫氳 */ close(sockfd); exit(1); } } return 0; event_test(); } int drawsreen(){ image = SDL_LoadBMP("./bg.bmp"); if (image == NULL) { fprintf(stderr, "涓嶈兘涓嬭浇鍥剧墖, %s\n", SDL_GetError()); return -1; } if (SDL_BlitSurface(image, NULL, screen, NULL) < 0) { //瑙i噴涓€涓婲ULL锛岀涓€涓槸鎸夌収image鐨勫昂瀵告樉绀猴紝绗簩涓槸榛樿鏄剧ず fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); return -1; } boxColor(screen, 10, 320,50, 360,0xff8f66); boxColor(screen, 60, 320,100, 360,0xff8f66); boxColor(screen, 110, 320,150, 360,0xff8f66); boxColor(screen, 160, 320,200, 360,0xff8f66); boxColor(screen, 210, 320,250, 360,0xff8f66); boxColor(screen, 260, 320,300, 360,0xff8f66); boxColor(screen, 310, 320,350, 360,0xff8f66); boxColor(screen, 360, 320,400, 360,0xff8f66); boxColor(screen, 410, 320,450, 360,0xff8f66); boxColor(screen, 460, 320,500, 360,0xff8f66); stringColor(screen, 30, 340,"Q",0x000000FF); stringColor(screen, 80, 340,"W",0x000000FF); stringColor(screen, 130, 340,"E",0x000000FF); stringColor(screen, 180, 340,"R",0x000000FF); stringColor(screen, 230, 340,"T",0x000000FF); stringColor(screen, 280, 340,"Y",0x000000FF); stringColor(screen, 330, 340,"U",0x000000FF); stringColor(screen, 380, 340,"I",0x000000FF); stringColor(screen, 430, 340,"O",0x000000FF); stringColor(screen, 480, 340,"P",0x000000FF); SDL_UpdateRect(screen, 0, 0, 0, 0); } int init_SDL(){ //鍒濆鍖朣DL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { fprintf(stderr, "init SDL %s\n", SDL_GetError()); return -1; } atexit(SDL_Quit); screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); if (screen == NULL) { fprintf(stderr, "涓嶈兘璁剧疆 640x480x8 video mode %s\n",SDL_GetError()); return -1; } SDL_WM_SetCaption("TCP鑱婂ぉ绋嬪簭娴嬭瘯", NULL); } int event_test(){ while ( SDL_WaitEvent(&event) >= 0 ) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: printf("hello,world!!!"); SDL_UpdateRect(screen, 0, 0,0,0); exit(0); break; case SDL_QUIT: { printf("Quit requested, quitting.\n"); exit(0); } break; } } }
上面的关于SDL的代码是为了移植到ARM开发板上用的,
PC下编译的命令如下
gcc clientsdl.c -lpthread -o clientsdl -I/usr/local/include -L/usr/local/lib -lSDL -lSDL_image -lSDL_gfx
./clientsdl 127.0..0.1
ARM上的命令 arm-linux-gcc clientsdl.c -lpthread -o armclientsdl -I/usr/local/include -L/自己交叉编译库的路径 -lSDL -lSDL_image -lSDL_gfx
./armclientsdl 127.0..0.1
运行结果截图: