linux socket server and client

In a previous example we learnt about the basics of socket programming in C. In this example we shall build a basic ECHO client and server. The server/client shown here use TCP sockets or SOCK_STREAM.

Tcp sockets are connection oriented, means that they have a concept of independant connection on a certain port which one application can use at a time. The concept of connection makes TCP a "reliable" stream such that if errors occur, they can be detected and compensated for by resending the failed packets.

Server

Lets build a very simple web server. The steps to make a webserver are as follows :

1. Create socket
2. Bind to address and port
3. Put in listening mode
4. Accept connections and process there after.

Quick example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
     C socket server example
*/
 
#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write
 
int main( int argc , char *argv[])
{
     int socket_desc , client_sock , c , read_size;
     struct sockaddr_in server , client;
     char client_message[2000];
     
     //Create socket
     socket_desc = socket(AF_INET , SOCK_STREAM , 0);
     if (socket_desc == -1)
     {
         printf ( "Could not create socket" );
     }
     puts ( "Socket created" );
     
     //Prepare the sockaddr_in structure
     server.sin_family = AF_INET;
     server.sin_addr.s_addr = INADDR_ANY;
     server.sin_port = htons( 8888 );
     
     //Bind
     if ( bind(socket_desc,( struct sockaddr *)&server , sizeof (server)) < 0)
     {
         //print the error message
         perror ( "bind failed. Error" );
         return 1;
     }
     puts ( "bind done" );
     
     //Listen
     listen(socket_desc , 3);
     
     //Accept and incoming connection
     puts ( "Waiting for incoming connections..." );
     c = sizeof ( struct sockaddr_in);
     
     //accept connection from an incoming client
     client_sock = accept(socket_desc, ( struct sockaddr *)&client, (socklen_t*)&c);
     if (client_sock < 0)
     {
         perror ( "accept failed" );
         return 1;
     }
     puts ( "Connection accepted" );
     
     //Receive a message from client
     while ( (read_size = recv(client_sock , client_message , 2000 , 0)) > 0 )
     {
         //Send the message back to client
         write(client_sock , client_message , strlen (client_message));
     }
     
     if (read_size == 0)
     {
         puts ( "Client disconnected" );
         fflush (stdout);
     }
     else if (read_size == -1)
     {
         perror ( "recv failed" );
     }
     
     return 0;
}

The above code example will start a server on localhost (127.0.0.1) port 8888
Once it receives a connection, it will read some input from the client and reply back with the same message.
To test the server run the server and then connect from another terminal using the telnet command like this

$ telnet localhost 8888

Client

Now instead of using the telnet program as a client, why not write our own client program. Quite simple again

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
     C ECHO client example using sockets
*/
#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr
 
int main( int argc , char *argv[])
{
     int sock;
     struct sockaddr_in server;
     char message[1000] , server_reply[2000];
     
     //Create socket
     sock = socket(AF_INET , SOCK_STREAM , 0);
     if (sock == -1)
     {
         printf ( "Could not create socket" );
     }
     puts ( "Socket created" );
     
     server.sin_addr.s_addr = inet_addr( "127.0.0.1" );
     server.sin_family = AF_INET;
     server.sin_port = htons( 8888 );
 
     //Connect to remote server
     if (connect(sock , ( struct sockaddr *)&server , sizeof (server)) < 0)
     {
         perror ( "connect failed. Error" );
         return 1;
     }
     
     puts ( "Connected\n" );
     
     //keep communicating with server
     while (1)
     {
         printf ( "Enter message : " );
         scanf ( "%s" , message);
         
         //Send some data
         if ( send(sock , message , strlen (message) , 0) < 0)
         {
             puts ( "Send failed" );
             return 1;
         }
         
         //Receive a reply from the server
         if ( recv(sock , server_reply , 2000 , 0) < 0)
         {
             puts ( "recv failed" );
             break ;
         }
         
         puts ( "Server reply :" );
         puts (server_reply);
     }
     
     close(sock);
     return 0;
}

The above program will connect to localhost port 8888 and then ask for commands to send. Here is an example, how the output would look

$ gcc client.c && ./a.out
Socket created
Connected

Enter message : hi
Server reply :
hi
Enter message : how are you

Server to handle multiple connections

The server in the above example has a drawback. It can handle communication with only 1 client. Thats not very useful. One way to work around this is by using threads. A thread can be assigned for each connected client which will handle communication with the client.

Code example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
     C socket server example, handles multiple clients using threads
*/
 
#include<stdio.h>
#include<string.h>    //strlen
#include<stdlib.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write
#include<pthread.h> //for threading , link with lpthread
 
//the thread function
void *connection_handler( void *);
 
int main( int argc , char *argv[])
{
     int socket_desc , client_sock , c , *new_sock;
     struct sockaddr_in server , client;
     
     //Create socket
     socket_desc = socket(AF_INET , SOCK_STREAM , 0);
     if (socket_desc == -1)
     {
         printf ( "Could not create socket" );
     }
     puts ( "Socket created" );
     
     //Prepare the sockaddr_in structure
     server.sin_family = AF_INET;
     server.sin_addr.s_addr = INADDR_ANY;
     server.sin_port = htons( 8888 );
     
     //Bind
     if ( bind(socket_desc,( struct sockaddr *)&server , sizeof (server)) < 0)
     {
         //print the error message
         perror ( "bind failed. Error" );
         return 1;
     }
     puts ( "bind done" );
     
     //Listen
     listen(socket_desc , 3);
     
     //Accept and incoming connection
     puts ( "Waiting for incoming connections..." );
     c = sizeof ( struct sockaddr_in);
     
     
     //Accept and incoming connection
     puts ( "Waiting for incoming connections..." );
     c = sizeof ( struct sockaddr_in);
     while ( (client_sock = accept(socket_desc, ( struct sockaddr *)&client, (socklen_t*)&c)) )
     {
         puts ( "Connection accepted" );
         
         pthread_t sniffer_thread;
         new_sock = malloc (1);
         *new_sock = client_sock;
         
         if ( pthread_create( &sniffer_thread , NULL ,  connection_handler , ( void *) new_sock) < 0)
         {
             perror ( "could not create thread" );
             return 1;
         }
         
         //Now join the thread , so that we dont terminate before the thread
         //pthread_join( sniffer_thread , NULL);
         puts ( "Handler assigned" );
     }
     
     if (client_sock < 0)
     {
         perror ( "accept failed" );
         return 1;
     }
     
     return 0;
}
 
/*
  * This will handle connection for each client
  * */
void *connection_handler( void *socket_desc)
{
     //Get the socket descriptor
     int sock = *( int *)socket_desc;
     int read_size;
     char *message , client_message[2000];
     
     //Send some messages to the client
     message = "Greetings! I am your connection handler\n" ;
     write(sock , message , strlen (message));
     
     message = "Now type something and i shall repeat what you type \n" ;
     write(sock , message , strlen (message));
     
     //Receive a message from client
     while ( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
     {
         //Send the message back to client
         write(sock , client_message , strlen (client_message));
     }
     
     if (read_size == 0)
     {
         puts ( "Client disconnected" );
         fflush (stdout);
     }
     else if (read_size == -1)
     {
         perror ( "recv failed" );
     }
         
     //Free the socket pointer
     free (socket_desc);
     
     return 0;
}

Run the above server and connect from multiple clients and it will handle all of them. There are other ways to handle multiple clients, like select, poll etc. We shall talk about them in some other article. Till then practise the above code examples and enjoy.


(http://www.binarytides.com/server-client-example-c-sockets-linux/)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值