Linux网络编程--客户端连接服务器端让我们已经看到了client与server之间是如何建立连接的。接下来介绍它们之间如何建立tcp协议交互通信。
先看看服务器端代码:
###############################tcpserver.c#########################
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
int main() { int ld,sd; struct sockaddr_in skaddr; struct sockaddr_in from; socklen_t addrlen, length;
char buff[100],send_message[100]; int n; //建立一个socket if ((ld = socket (PF_INET, SOCK_STREAM, 0))<0) { perror("Problem creating socket/n"); exit(1); }
skaddr.sin_family = AF_INET; skaddr.sin_addr.s_addr = htonl (INADDR_ANY);//可以同任意主机通讯 skaddr.sin_port = htons(0);//任何指派一个端口b
if(bind(ld,(struct sockaddr *)&skaddr, sizeof (skaddr))<0){ perror("Problem binding/n"); exit(0); }
length = sizeof (skaddr); if (getsockname(ld, (struct sockaddr *)&skaddr, &length) <0) { perror("Error getsockname/n"); exit(1); } printf("The Server passive socket port number is %d/n", ntohs(skaddr.sin_port));//打印出随机的端口
if (listen(ld,5)<0) { perror("Error calling listen/n"); exit(1); }
while (1) { printf("Ready for a connection ... /n"); addrlen=sizeof(skaddr); if((sd = accept (ld, (struct sockaddr*) &from, &addrlen)) <0) { perror("Problem with accept call/n"); exit(1); }
printf("Got a connect - processing .../n"); length = sizeof (skaddr); if (getsockname (sd, (struct sockaddr*)&skaddr, &length)<0) { perror ("Error getsockname/n"); exit(1); }
printf("The active server port number is %d/n", ntohs (skaddr.sin_port)); printf("The active server IP ADDRESS is %s/n" ,inet_ntoa (skaddr.sin_addr));
printf("The client port number is %d/n", ntohs(from.sin_port)); printf("The client IP ADDRESS is %s/n",inet_ntoa(from.sin_addr));
while ((n=read(sd,buff,100))>0) {//一旦缓冲区部为空的时候读出数据 printf("%s/n","Client say:"); write (1,buff,n); printf("%s/n","Server say:"); fgets(send_message,100,stdin); write (sd,send_message,strlen(send_message)); }
printf("Done with connection -closing/n/n/n"); close (sd); } }
|
从服务器端的代码可以看出:与客户端的交流是比较不灵活的,因为当server读出client发送过来的buff,将结果显示出来之后,打 印"Server say:"接着执行fget操作,等待用户输入资料。此时client可能就无法输入或者发送新的buff给server.接下来看看client代码:
########################tcpclient.c###########################
#include <stdio.h> /* standard C i/o facilities */ #include <stdlib.h> /*needed for atoi() */ #include <unistd.h> /*Unix System Calls */ #include <sys/types.h> /*system data type definition */ #include <netinet/in.h> /* INET constants and stuff */ #include <sys/socket.h> /* socket specific definitions */ #include <arpa/inet.h> /*IP address conversion stuff */
char message_recv[100]; char message_send[100];
int main( int argc, char **argv) { int sk; struct sockaddr_in skaddr;
if (argc != 3) { printf("Usage: client <server name> <server port>/n"); exit(0); }
if ((sk =socket(PF_INET, SOCK_STREAM, 0)) <0 ) { printf("Problem creating socket /n"); exit(1); }
skaddr.sin_family = AF_INET;
if (inet_aton(argv[1], &skaddr.sin_addr) ==0) { printf("Invalid IP address : %s/n", argv[1]);//ip address exit(1); }
skaddr.sin_port = htons (atoi(argv [2]));//port number
if (connect (sk, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) { printf("Problem connecting socket /n"); exit(1); }
while (1){ printf("%s/n","Client says:"); fgets(message_send,sizeof(message_send),stdin); write(sk, message_send, strlen(message_send)); read (sk, message_recv, 100); printf("%s/n","Server says:"); write(1, message_recv,100); }
close(sk); return(0); }
|
客户端的while下的操作与server相差无几。所以彼此之间的操作正如前面所说的。不灵活。不能彼此随心所欲的童心。
执行程序:
服务器端:
bash-2.05a$ gcc -o tcpclient tcpclient.c
bash-2.05a$ ./tcpserver
The Server passive socket port number is 53180
Ready for a connection ...
Got a connect - processing ...
The active server port number is 53180
The active server IP ADDRESS is 127.0.0.1
The client port number is 53181
The client IP ADDRESS is 127.0.0.1
Client say:
hello
Server say:
what can i do for u sir
客户端:
bash-2.05a$gcc -o tcpclient tcpclient.c
bash-2.05a$ ./tcpclient 127.0.0.1 53180
Client says:
hello
Server says:
what can i do for u sir
Client says:
如果客户端执行命令行为:bash-2.05a$ ./tcpclient localhost 53180
就会出现如下的错误:
Invalid IP address : localhost
问题很简单:在相当于地址解析错误。gethostname()可以帮助我们解决问题:
####################tcpclient1.c#########################
#include <stdio.h> /* standard C i/o facilities */ #include <stdlib.h> /*needed for atoi() */ #include <unistd.h> /*Unix System Calls */ #include <sys/types.h> /*system data type definition */ #include <netinet/in.h> /* INET constants and stuff */ #include <sys/socket.h> /* socket specific definitions */ #include <arpa/inet.h> /*IP address conversion stuff */ #include <netdb.h> /* Name lookups (gethostbyname) */
char message_recv[100]; char message_send[100];
int main( int argc, char **argv) { int sk; struct sockaddr_in skaddr; struct hostent *hp;
if (argc != 3) { printf("Usage: client <server name> <server port>/n"); exit(0); }
if ((sk =socket(PF_INET, SOCK_STREAM, 0)) <0 ) { printf("Problem creating socket /n"); exit(1); }
skaddr.sin_family = AF_INET;
if (( hp= gethostbyname(argv[1])) !=0){//地址解析 memcpy( &skaddr.sin_addr.s_addr, hp->h_addr, hp->h_length); } else {
if (inet_aton(argv[1], &skaddr.sin_addr) ==0) { printf("Invalid IP address : %s/n", argv[1]); exit(1); } }
skaddr.sin_port = htons (atoi(argv [2]));
if (connect (sk, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) { printf("Problem connecting socket /n"); exit(1); }
while (1){ printf("%s/n","Client says:"); fgets(message_send,sizeof(message_send),stdin); write(sk, message_send, strlen(message_send)); read (sk, message_recv, 100); printf("%s/n","Server says:"); write(1, message_recv,100); }
close(sk); return(0); }
|
这样地址解析的问题就可以得到解决了。
客户端:
bash-2.05a$ ./tcpclient1 127.0.0.1 53194
Client says:
lsdf
^[[A^C
bash-2.05a$ ./tcpclient1 localhost 53194
Client says://这里不再提是错误
fgf
-------------------------ENJOY-------------------------------